Reddit 如何统计每个帖子的浏览量,reddit如何统计每个帖子的浏览量Reddit如何统计每个帖子的浏览量之前没听说过HyperLogLog,翻译这篇文章也就学习这么简单。欢迎来错~我们想更好地向用户展示Reddit的规模。对于这一点,投票数和评论数是一个帖子最重要的指标。然而,Reddit上相当一部分用户只是浏......
之前没听说过HyperLogLog,翻译这篇文章也就学习这么简单。欢迎来错~
我们想更好地向用户展示Reddit的规模。对于这一点,投票数和评论数是一个帖子最重要的指标。然而,Reddit上相当一部分用户只是浏览内容,既没有投票也没有评论。所以我们想建立一个系统,可以计算一个帖子的浏览量。这个数字会显示给帖子的创建者和版主,让他们更好的了解一个帖子的活跃度。
在这篇博客中,我们将讨论如何实现对海量数据的计数。
计算机
我们对计数系统有四个主要要求:
查看的帖子数量必须是实时或接近实时的,而不是每天或每小时。
同一用户在短时间内多次访问一个帖子,只计一次浏览量。
显示的页面浏览量和真实的页面浏览量之间允许有多大的百分比误差
Reddit是全球访问量第八大的网站,所以系统应该能在生产环境的规模上正常运行,只允许有几秒钟的延迟。
满足以上四个需求,远比听起来难。为了实时准确地统计,我们需要知道某个用户是否曾经访问过这个帖子。为了了解这些信息,我们必须为每个帖子维护一个访问用户集合,然后在每次计算页面浏览量时检查该集合。naive的实现是将访问用户的集合存储在内存的hashMap中,以post Id作为键。
这种实现方式对于低流量的帖子是可行的,但是一旦某个帖子变得热门,流量剧增时就很难控制了。甚至有些帖子的独立访客超过100万对于这类帖子,存储独立访问者的ID,频繁查询某个用户之前是否访问过,会对内存和CPU造成很大的负担。
因为我们不能提供精确的计数,所以我们研究了几种不同的基数估计算法。有两个选项可以满足我们的需求:
一种是线性概率计数法,这种方法非常精确,但是当计数集变大时,所需内存会线性变大。
第二种是基于超对数的计数方法(以下简称HLL)。HLL空间复杂度低,但其精度不如线性计数。
让我们来看看HLL将节省多少内存。如果我们需要存储100万独立访问者的ID,每个用户ID的长度为8个字节,那么我们需要8 M的内存来存储一个帖子的独立访问者。相反,如果采用HLL,内存占用会显著减少。HLL的不同实现消耗不同的内存。如果采用本文的实现方法,存储100万个id只需要12 KB,是原来的0.15%
大数据计数:如何仅用1.5 KB内存计数十亿个不同的对象——高可扩展性——本文很好地总结了上述算法。
HLL的许多实现结合了上述两种算法。当集合规模较小时,采用线性计数,当集合规模达到一定阈值时,切换到HLL。前者通常被称为“稀疏的)HLL,而后者被称为“稠密的)HLL。这种结合了两种算法的实现具有很大的优势,因为它既能保证小集合的准确性,又能保证大集合的准确性,同时还能保证适度的内存增长。你可以在google的这篇论文中了解到这个实现的细节。
论文链接
https://antirez.com/news/75
现在我们已经决定采用HLL算法,但是在选择具体的实现方式时,我们考虑了以下三种不同的实现方式。因为我们的数据工程团队用的是Java和Scala,所以我们只考虑Java和Scala的实现。
Twitter提供的Algebird是Scala实现的。Algebird有很好的文档,但是他们不容易理解稀疏和密集HLL的实现细节。
streamlib中提供的HyperLogLog++是用Java实现的。streamlib中的代码文档是完整的,但其中一些很难理解如何正确使用它们并转换它们以满足我们的需求。
Redis HLL实施,这是我们最终的选择。我们认为Redis中HLLs的实现文档是完整的,易于配置,提供的相关API也易于集成。另一个优势是,我们可以部署专用服务器,从而降低性能压力。
Reddit的数据管道依赖于卡夫卡。当用户访问一个博客时,会触发一个事件,该事件会被发国际快递事件收集服务器,并在Kafka中持久化。
之后,计数系统将依次运行这两个组件。在我们的计数系统架构中,第一部分是一个Kafka消费者,我们称之为Nazar。Nazar会从Kafka读取每一个事件,它会通过一系列配置好的规则来判断事件是否需要计数。我们取这个名字只是因为Nazar是一个眼睛形状的护身符,而“Nazar”系统就像眼睛一样,让我们的计数系统远离恶意者的破坏。我们不统计一次事件的原因之一是同一用户短时间内重复访问。Nazar将修改事件,添加一个布尔标志,指示是否应该计数,并将事件放回Kafka。
系统的第二部分来了。我们称之为第二个卡夫卡消费算盘,用于计算真实浏览量,并将计算结果显示在网站或客户端。Abacus从Kafka读取Nazar处理的事件,根据Nazar的处理结果决定是跳过这个事件还是加入计数。如果在Nazar中处理的结果是您可以加入计数,那么Abacus将首先检查与该事件相关联的帖子是否已经在Redis中有HLL计数器。如果已经存在,Abacus将向Redis发快递PFADD请求。如果不存在,那么Abacus将向Cassandra cluster (Cassandra用于持久化HLL计数器和计数值)发快递一个请求,然后向Redis发快递一个SET请求。这通常发生在当一个网民访问一个旧帖子时,此时该帖子的计数器可能已经在Redis中过期。
为了存储Redis中存储的计数器过期的旧帖子的页面视图。Abacus会定期将Redis中每个帖子的所有HLL和页面浏览量写入Cassandra cluster。为了避免集群过载,我们以10秒为周期批量写入。
下图显示了事件流的一般流程:
摘要
我们希望浏览量可以让发帖人知道帖子的所有访问量,也可以帮助版主快速定位自己社区中访问量高的帖子。未来,我们计划利用我们数据管道的实时潜力,为Reddit用户提供更多有用的反馈。
特别声明:以上文章内容仅代表作者本人观点,不代表ESG跨境电商观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与ESG跨境电商联系。
二维码加载中...
使用微信扫一扫登录
使用账号密码登录
平台顾问
微信扫一扫
马上联系在线顾问
小程序
ESG跨境小程序
手机入驻更便捷
返回顶部