玩转Redis-HyperLogLog统计微博日活月活
名词解释
DAU(Daily Active User)日活跃用户数量
常用于反映网站、互联网应用或网络游戏的运营情况。DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户)
月活跃用户数量(Monthly Active User,MAU)
月活跃用户数量通常统计一个月(统计月)之内,登录或使用了某个产品的用户数(去除重复登录的用户)
Note:日活、月活反映用户的活跃度,但是无法反映用户的粘性。
日活数据统计面临哪些挑战
2020年2月26日,微博发布2019年第四季度及全年财报。数据显示,截至2019年底,微博月活跃用户达到5.16亿,相比2018年年底净增长约5400万,其中移动端占比94%。2019年微博全年营收提升至122.4亿元,其中广告营收达到106亿元。
Bitmaps可用于统计日活吗?
前文《玩转Redis-京东签到领京豆如何实现》提到了 Bitmaps 在大数据下的应用,那么Bitmaps可以用于统计日活数据吗?我们来做个计算分析(以一亿用户为例):
统计方式 | 占用计算 | 1亿用户占用空间(M) |
---|---|---|
MySQL 32bit的int数据类型 | 1个int所需存储空间为4字节,可存储32 bit位 | 10^8 / (1024 1024 8 / 32) ≈ 381 M |
Redis Bitmaps | Bitmaps单个支持512M,不像int单个仅存储32位 | 10^8 / (1024 1024 8) ≈ 12M |
使用Bitmaps计算日活月活:
- 计算日活:bitcount key获取key为1的数量
- 计算月活:可把30天的所有bitmap做or计算,再进行bitcount计算
- 计算留存率:昨日留存=昨天今天连续登录的人数/昨天登录的人数,即昨天的bitmap与今天的bitmap进行and计算,在除以昨天bitcount的数量
通过以上计算,我们发现Bitmaps已经很节省空间了。统计一个网站的日活已不在话下,但是大型互联网公司除了日活,还有UV、PV等等需要统计。面对上千甚至更多的需统计模块,1个模块1天需要12M,一年就需要12M * 365 / 1024 ≈ 4.3G
,1000个模块一年就需要12M * 365 / 1024 / 1024 ≈ 4.2T
。So 革命尚未成功,我们还需再节省点!
日活数据统计的特点
- 数据需要去重
- 数据允许有一定的偏差,101W和102W差距不大
- 占用空间尽可能小
HyperLogLog介绍
HyperLogLog必知
HyperLogLog(HLL)是一种用于基数计算的概率数据结构,通俗的说就是支持集合中不重复元素的统计。
常规基数计算需要准备一块内存空间用于存储已经计数的元素,避免某些元素被重复统计。Redis提供了一种用精度来换取内存空间的算法,标准误差低于1%。仅需要12K 就能完成统计(再加上HLL自身所需的一点bytes),如果HyperLogLog中的元素较少,所需内存空间更小。HyperLogLogs的标准误差是0.81%。
输入元素数量或体积非常大时,HLL所需空间固定且很小。12kb内存可计算接近 2^64 个不同元素的基数。
HyperLogLog虽然技术实现是一种不同的数据结构,但底层依旧是Redis strings,所以可以使用GET命令获取序列化后的数据,使用SET命令反序列化数据存储到Redis。
HyperLogLog和Sets的区别
对比/数据类型 | Sets | HyperLogLog |
---|---|---|
是否实际存储统计元素 | 存储 | 不存储元素,仅存储存在的标记 |
增加元素 | SADD | PFADD |
统计元素数量 | SCARD | PFCOUNT |
删除元素 | SREM | 不支持删除元素 |
HyperLogLog如何使用
HyperLogLog核心命令:PFADD、PFCOUNT、PFMERGE
HyperLogLog命令对比分析
命令 | 功能 | 参数 |
---|---|---|
PFADD | 添加元素到HLL数据结构 | key element [element ...] |
PFCOUNT | 返回HLL的基数值 | key [key ...] |
PFMERGE | 合并多个HLL结构数据到destkey | destkey sourcekey [sourcekey ...] |
HLL操作命令中的PF含义:HyperLogLog 数据结构的发明人 Philippe Flajolet 的首字母缩写。
HyperLogLog命令详解
HyperLogLog命令注意事项
- PFADD仅存储标记,不存储元素本身
- PFCOUNT实际是一个write命令,执行PFCOUNT时可能会重新计算计数值并存储
- key有多个时,PFCOUNT会动态合并计算,并且计算结果不会被缓存,所以生产环境执行PFCOUNT时尽量避免带多个key
- key有多个时,PFCOUNT是先合并再计算,结果为多个对象合并<去重>后的基数值(注意:不是基数值之和)
- PFMERGE计算的是sourcekey的并集
- 如果destkey已存在,则PFMERGE执行后destkey最终的结果是dest+source的并集
HyperLogLog命令示例
// pfadd、pfcount 示例
127.0.0.1:6379> pfadd hll 1
(integer) 1
127.0.0.1:6379> pfadd hll 1
(integer) 0
127.0.0.1:6379> pfadd hll 2 3 4
(integer) 1
127.0.0.1:6379> pfcount hll
(integer) 4
127.0.0.1:6379> pfcount hll:notexist
(integer) 0
127.0.0.1:6379> pfadd hll2 a b
(integer) 1
127.0.0.1:6379> pfcount hll2
(integer) 2
127.0.0.1:6379> pfcount hll hll2
(integer) 6
127.0.0.1:6379> get hll
"HYLL\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00A\xee\x84[v\x80Mt\x80Q,\x8cC\xf3"
127.0.0.1:6379> set hll:error error666
OK
127.0.0.1:6379> pfcount hll:error
(error) WRONGTYPE Key is not a valid HyperLogLog string value.
// pfmerge 示例
127.0.0.1:6379> pfadd hllm1 1 2 3 4 5
(integer) 1
127.0.0.1:6379> pfadd hllm2 5 6 7 8
(integer) 1
127.0.0.1:6379> pfmerge hllm3 hllm1 hllm2
OK
127.0.0.1:6379> pfcount hllm3
(integer) 8
127.0.0.1:6379> pfadd hllm4 7 8 9 10 11 12 14 14
(integer) 1
127.0.0.1:6379> pfmerge hllm4 hllm1 hllm2
OK
127.0.0.1:6379> pfcount hllm4
(integer) 13
HyperLogLog应用场景
网站日活月活
- 日活:每天一个HLL,用户登录时则
PFADD HLL20200719 userID
; - 月活:合并当月的所有日活数据
PFMERGE HLL202007 HLL20200701 HLL20200702 HLL20200703 ...
网页UV
UV(Unique Visitor)独立访客:1天内;cookie为标识;相同的客户端多次访问只计为1个访客。
比如老板想实时查看公司网站某些页面从今天0点到现在被多少独立访客访问。
其他场景场景
- 搜索引擎关键词搜索量
- 用户在线人数统计
- 基于基数计数的数据分析场景
转载至:https://zxiaofan.blog.csdn.net/article/details/107449335
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/04/01/playing-redis-hyperloglog-to-count-daily-and-monthly-activities-on-weibo/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论