在移动应用的业务场景中,我们需要保存这样的信息:一个 key 关联了一个数据集合,同时还要对集合中的数据进行统计排序。
常见的场景如下:
-
给一个 userId ,判断用户登陆状态;
-
两亿用户最近 7 天的签到情况,统计 7 天内连续签到的用户总数;
-
统计每天的新增与第二天的留存用户数;
-
统计网站的对访客(Unique Visitor,UV)量
-
最新评论列表
-
根据播放量音乐榜单
通常情况下,我们面临的用户数量以及访问量都是巨大的,比如百万、千万级别的用户数量,或者千万级别、甚至亿级别的访问信息。
所以,我们必须要选择能够非常高效地统计大量数据(例如亿级)的集合类型。
如何选择合适的数据集合,我们首先要了解常用的统计模式,并运用合理的数据来解决实际问题。
四种统计类型:
-
二值状态统计;
-
聚合统计;
-
排序统计;
-
基数统计。
本文将用到 String、Set、Zset、List、hash 以外的拓展数据类型 Bitmap
、HyperLogLog
来实现。
文章涉及到的指令可以通过在线 Redis 客户端运行调试,地址:https://try.redis.io/,超方便的说。
基数统计
❝基数统计:统计一个集合中不重复元素的个数,常见于计算独立用户数(UV)。
实现基数统计最直接的方法,就是采用集合(Set)这种数据结构,当一个元素从未出现过时,便在集合中增加一个元素;如果出现过,那么集合仍保持不变。
当页面访问量巨大,就需要一个超大的 Set 集合来统计,将会浪费大量空间。
另外,这样的数据也不需要很精确,到底有没有更好的方案呢?
这个问题问得好,Redis 提供了 HyperLogLog
数据结构就是用来解决种种场景的统计问题。
HyperLogLog
是一种不精确的去重基数方案,它的统计规则是基于概率实现的,标准误差 0.81%,这样的精度足以满足 UV 统计需求了。
关于 HyperLogLog 的原理过于复杂,如果想要了解的请移步:
-
https://www.zhihu.com/question/53416615
-
https://en.wikipedia.org/wiki/HyperLogLog