今天就跟大家聊聊有关Reddit中怎么统计每个帖子的浏览量,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
计数机制
对于计数系统我们主要有四种需求:
帖子浏览数必须是实时或者近实时的,而不是每天或者每小时汇总。
同一用户在短时间内多次访问帖子,只算一个浏览量
显示的浏览量与真实浏览量间允许有小百分之几的误差
Reddit 是全球访问量第八的网站,系统要能在生产环境的规模上正常运行,仅允许几秒的延迟
要全部满足以上四个需求的困难远远比听上去大的多。为了实时精准计数,我们需要知道某个用户是否曾经访问过这篇帖子。想要知道这个信息,我们就要为每篇帖子维护一个访问用户的集合,然后在每次计算浏览量时检查集合。一个 naive 的实现方式就是将访问用户的集合存储在内存的 hashMap 中,以帖子 Id 为 key。
这种实现方式对于访问量低的帖子是可行的,但一旦一个帖子变得流行,访问量剧增时就很难控制了。甚至有的帖子有超过 100 万的独立访客! 对于这样的帖子,存储独立访客的 ID 并且频繁查询某个用户是否之前曾访问过会给内存和 CPU 造成很大的负担。
因为我们不能提供准确的计数,我们查看了几种不同的基数估计算法。有两个符合我们需求的选择:
一是线性概率计数法,很准确,但当计数集合变大时所需内存会线性变大。
二是基于 HyperLogLog (以下简称 HLL )的计数法。 HLL 空间复杂度较低,但是精确度不如线性计数。
下面看下 HLL 会节省多少内存。如果我们需要存储 100 万个独立访客的 ID, 每个用户 ID 8 字节长,那么为了存储一篇帖子的独立访客我们就需要 8 M的内存。反之,如果采用 HLL 会显著减少内存占用。不同的 HLL 实现方式消耗的内存不同。如果采用这篇文章的实现方法,那么存储 100 万个 ID 仅需 12 KB,是原来的 0.15%!!
Big Data Counting: How to count a billion distinct objects using only 1.5KB of Memory – High Scalability –这篇文章很好的总结了上面的算法。
许多 HLL 的实现都是结合了上面两种算法。在集合小的时候采用线性计数,当集合大小到达一定的阈值后切换到 HLL。前者通常被成为 ”稀疏“(sparse) HLL,后者被称为”稠密“(dense) HLL。这种结合了两种算法的实现有很大的好处,因为它对于小集合和大集合都能够保证精确度,同时保证了适度的内存增长。
现在我们已经确定要采用 HLL 算法了,不过在选择具体的实现时,我们考虑了以下三种不同的实现。因为我们的数据工程团队使用 Java 和 Scala,所以我们只考虑 Java 和 Scala 的实现。
Twitter 提供的 Algebird,采用 Scala 实现。Algebird 有很好的文档,但他们对于 sparse 和 dense HLL 的实现细节不是很容易理解。
stream-lib中提供的 HyperLogLog++, 采用 Java 实现。stream-lib 中的代码文档齐全,但有些难理解如何合适的使用并且改造的符合我们的需求。
Redis HLL 实现,这是我们最终选择的。我们认为 Redis 中 HLLs 的实现文档齐全、容易配置,提供的相关 API 也很容易集成。还有一个好处是,我们可以用一台专门的服务器部署,从而减轻性能上的压力。
Reddit 的数据管道依赖于 Kafka。当一个用户访问了一篇博客,会触发一个事件,事件会被发送到事件收集服务器,并被持久化在 Kafka 中。
之后,计数系统会依次顺序运行两个组件。在我们的计数系统架构中,***部分是一个 Kafka 的消费者,我们称之为 Nazar。Nazar 会从 Kafka 中读取每个事件,并将它通过一系列配置的规则来判断该事件是否需要被计数。我们取这个名字仅仅是因为 Nazar 是一个眼睛形状的护身符,而 ”Nazar“ 系统就像眼睛一样使我们的计数系统远离不怀好意者的破坏。其中一个我们不将一个事件计算在内的原因就是同一个用户在很短时间内重复访问。Nazar 会修改事件,加上个标明是否应该被计数的布尔标识,并将事件重新放入 Kafka。
下面就到了系统的第二个部分。我们将第二个 Kafka 的消费者称作 Abacus,用来进行真正浏览量的计算,并且将计算结果显示在网站或客户端。Abacus 从 Kafka 中读取经过 Nazar 处理过的事件,并根据 Nazar 的处理结果决定是跳过这个事件还是将其加入计数。如果 Nazar 中的处理结果是可以加入计数,那么 Abacus 首先会检查这个事件所关联的帖子在 Redis 中是否已经存在了一个 HLL 计数器。如果已经存在,Abacus 会给 Redis 发送个 PFADD 的请求。如果不存在,那么 Abacus 会给 Cassandra 集群发送个请求(Cassandra 用来持久化 HLL 计数器和 计数值的),然后向 Redis 发送 SET 请求。这通常会发生在网友访问较老帖子的时候,这时该帖子的计数器很可能已经在 Redis 中过期了。
为了存储存在 Redis 中的计数器过期的老帖子的浏览量。Abacus 会周期性的将 Redis 中全部的 HLL 和 每篇帖子的浏览量写入到 Cassandra 集群中。为了避免集群过载,我们以 10 秒为周期批量写入。
下图是事件流的大致流程:
看完上述内容,你们对Reddit中怎么统计每个帖子的浏览量有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。