面试题:请问,某视频点播网站,希望实时展现热门视频,比如近8小时点击量最大的前100个视频。如果由你来开发这个功能,你怎么做?

一、思路分析

看到这样的一个问题,估计同学们会说,很简单呀,用Redis的SortedSet搞定啊,Score计数,Key是视频ID,不就OK了吗?

回答到这一步,只能说你回答的不错,下一位。too young too simple呀兄弟。

要听清楚题目,有8小时动态时间窗口,计数会过期的。还有,一个视频播放网站的量有这么小吗,一个Redis就搞定了?我告诉你,视频数据起码是百万级别了,用户几个亿,播放量你至少得估计个1000/s吧。

这么看下来,还觉得是一个Redis能解决得了的吗?

二、解决办法

数据量太大,肯定要使用分布式了。关于数据的接收、存储本章我们先不考虑,我们只分析如何统计某个时间段内的播放量排行。

我们需要一张表来记录每条视频的点击记录(包含时间,用户等信息),我们要统计的就是某个时间段的点击总次数。

如果只有一张表,而且数据也存储在数据库中,那这个sql就简单了,语句如下:当天播放量前100视频排行榜

SELECT( e.createTime ) AS HOUR,ROUND( sum( e.score ), 1 ) AS sum,id
FROMt_vedio_play e
WHEREto_days( e.playTime ) = to_days( now( ) )
order by score desc limit 100

视频量太大,一张表放不下所有的记录,就需要用到分治算法,先将表哈希拆分成1024张子表。每张表里有一个字段score,表示这个视频的点击数(其实就是1,我们记录的是每一个时间点的每一次点击行为,后面再对时间进行分段抽象)。

如果是多个子表,你得在每个子表上都进行一次TopN查询,然后聚合结果再做一次TopN查询。子表查询可以多线程并行,提高聚合效率。下面是伪代码:

candidates = []
for k in range(1024):# 每个表都取topnrows = select id, score from vedio_${k} order by score desc limit 100# 聚合结果candidates.extend(rows)
# 根据score倒排
candidates = sorted(candidates, key=lambda t: t[1], reverse=True)
# 再取topn
candidates[:100]

上面这个算法思想,实际上就是分而治之,我们通过把一个大问题拆分成多个小问题并行处理以提高效率。

三、进一步优化

8小时的滑动窗口,意味着新的数据源源不断的进来,旧的数据时时刻刻在淘汰。严格来说,精准的8小时滑动窗口要求每条数据要严格的过期,差了1秒都不行,到点了就立即被淘汰。

精准的代价是我们要为每条点击记录都设置过期时间,过期时间本身也是需要存储的,而且过期策略还需要定时扫描时间堆来确认哪些记录过期了。量大的时候这些都是不容小嘘的负担。

但是在业务上来讲,排行版没有必要做到如此的精准,偏差个几分钟这都不是事。

业务上的折中给服务的资源优化带来了机遇。我们对时间片进行了切分,一分钟一个槽来进行计数。下面是伪代码:

class HitSlot {long timestamp; # earlies timestampmap[int]int hits;  # post_id => hitsvoid onHit(int postId, int hits) {this.hits[postId] += hits;}
}
class WindowSlots {HitSlot currentSlot;  # current active slotsLinkedList<HitSlot> historySlots;  # history unactive slotsmap[int]int topHits; # topn postsvoid onHit(int postId, int hits) {  # 因为上游有合并点击,所以有了hits参数long ts = System.currentTimeMillis();if(this.currentSlot == null) { # 创建第一个槽this.currentSlot == new HitSlot(ts);} elif(ts - this.currentSlot.timestamp > 60 * 1000) {  # 创建下一个槽,一分钟一个槽this.historySlots.add(this.currentSlot);this.currentSlot = new HitSlot(ts);}this.currentSlot.onHit(postId, hits);}void onBeat() {  # 维护窗口,移除过期的槽,然后统计topn,30s~60s调用一次if(historySlots.isEmpty()) {return;}HitSlot slot = historySlots[0];long ts = System.currentTimeMillis();if(ts - slot.timestamp > 8 * 60 * 60 * 1000) {  # 过期了8小时,移掉第一个historySlots.remove(0);# 计算topn的帖子            topHits = topn(aggregateSlots(historySlots));  }}
}

上面的代码代表着每个分布式子节点的逻辑,它的目标就是定时维持一个8小时的统计窗口,并汇聚TopN的热门视频放在内存里。这个TopN的数据并不是特别实时,有一个大约1分钟的短暂的时间窗口。

四、统计中用到的Hash

按照视频的数据至少几百万,如果每个子节点都要对所有的播放量统计】,似乎也会占用不少内存,聚合和排序也会有不少计算量。最好的想法是每个子节点只负责一部分视频播放量的统计,这样可以明显节省计算资源。


我的微信公众号:架构真经(id:gentoo666),分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。每日更新哦!

参考资料:

  1. https://blog.csdn.net/bntX2jSQfEHy7/article/details/80276225

算法高级(25)-分布式TopN算法玄机相关推荐

  1. 算法高级(1)-概述

    算法是对特定问题求解步骤的描述.对于同一个问题,我们可能会用不同的算法来求解,我们可以根据算法的可读性.效率等进行取舍.针对不同的数据保存方式,也会有不同的算法. 很多同学会觉得,我工作经验五年,工作 ...

  2. 【Flink】分布式快照算法—— Chandy-Lamport 算法

    文章目录 1.概述 2. Overview 3. Global Snapshot 4.Chandy-Lamport 算法 5.例子 6.总结 7.Refer 1.概述 转载:https://blog. ...

  3. 分布式一致性算法——Paxos 和 Raft 算法

    写在前面 本文隶属于专栏<100个问题搞定大数据理论体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见100个问题搞定大数据理 ...

  4. 分布式优化算法的背景,应用场景,研究动态

    文章目录 0.写在前面 1.背景介绍 ① 概念解释 ② 应用背景 ③ 小结 2.研究动态与现状 ①分布式优化算法的数学模型 ②分布式优化算法的分类 ③ 有中心节点VS无中心节点 ④有向图和无向图 ⑤静 ...

  5. [Spark的TopN算法实现]

    一.TopN算法 MapReduce中的TopN算法是一个经典的算法,由于每个map都只是实现了本地的TopN算法,而假设map有M个,在归约的阶段只有M x N次运算,这个结果是可以接受的并不会造成 ...

  6. TopN算法实战 排序算法RangePartitioner解密

    1.基础TopN算法实战 2.分组TopN算法实战 3.排序算法RangePartitioner内幕解密 知识点: *只要是改变每一行列的数据,一般都是用Map操作 *RangePartitioner ...

  7. 分布式共识算法丨Raft丨Raft-Extended 论文翻译

    Raft-Extended 翻译 原文:https://pdos.csail.mit.edu/6.824/papers/raft-extended.pdf 辨析 consensus vs consis ...

  8. Thrill: 基于C++的高性能分布式批处理算法

    Thrill: 基于C++的高性能分布式批处理算法 摘要 1.介绍 概述 我们的贡献 A 相关工作 2.Thrill设计 A. 分布式的不可变数组 B. 示例:WordCount C. DIA操作总览 ...

  9. 一致性hash算法_分布式寻址算法

    一.分布式寻址算法简介 分布式寻址算法是很重要的内容,不了解这些算法,也就不能透彻的了解各种分布式中间件的原理.简单说一下这些高大上的寻址到底是个啥意思,比如在elasticsearch中,采用的是多 ...

最新文章

  1. 基于OpenCV实战的图像处理:色度分割
  2. IBM斥资3.6亿美元建史上最复杂云计算中心
  3. mongoose操作mongodb
  4. 网页html语言怎么看,怎样查看网页的css代码?
  5. Minio服务限制/租户
  6. Apache 和 Tomcat 的 关系
  7. 大前端技术选型 Native原生iOS, Android, React-Native, Flutter, 微信小程序, HTML5
  8. 以风险管理思想构建关键信息基础设施风险评估重器
  9. Adobe Dreamweaver CS6(或者CC 2018.2 SP)安装失败解决方案
  10. 文科生 python 简书_文科生学 Python 系列 15:泰坦尼克数据 1
  11. 竟有比双十一更令人发指的福利……
  12. word中统一修改mathtype公式和大小对应
  13. 如何在线压缩PDF文件大小?
  14. Log slf4j+logback配置
  15. 70 告别了,2013-2021【2021-06-05 1854】
  16. MySQL修改自增字段的自增值
  17. 一文查看公信宝查封始末,CEO此前曾表示获利数千万
  18. Advanced Installer多语言包安装
  19. PooledDataSource forcefully closed/removed all connections的解决
  20. invoke,十分钟搞定强大的Python任务自动化工具

热门文章

  1. MySQL去除查询结果重复值
  2. Qt控件中的属性sizePolicy说明
  3. codepage IMLangCodePages
  4. Exchange Server 2010 SP3部署
  5. pl/sql developer 中文字段显示乱码
  6. 虚拟桌面的备份恢复最佳实践 第二部分
  7. eclipse项目导入到AndroidStudioc报错
  8. python--文件
  9. require.js使用(一)
  10. 使用百度链的智能合约来落地公司业务场景