HyperLogLog 是什么
HyperLogLog 是一种基数估算结构:它不记录具体有哪些元素,只用一个固定的位数组统计「大致有多少个不同元素」。Redis 把它实现成一个特殊编码的字符串,每个键固定占用约 12KB(16384 个 6 位寄存器),无论统计一亿还是一万个元素,内存几乎不变,标准误差约 0.81%。适合「只关心去重后的总数」的场景,例如日活、独立访客、关键词覆盖量。
基本信息
| 内存 | 每键约 12KB,与元素数量无关;稀疏编码时占用更少 |
|---|---|
| 误差 | 标准误差约 0.81%,结果不是精确值 |
| 写入 | PFADD key element1 element2 ... |
| 读取 | PFCOUNT key 或 PFCOUNT k1 k2 直接给多键合并基数 |
| 合并 | PFMERGE dest src1 src2 ...,把多个 HLL 合并成一个 |
典型使用场景
- 日活与 UV 统计:每天一个键,PFADD 记录用户标识,PFCOUNT 得到当日去重人数
- 周活跃与月活跃:用 PFMERGE 把若干天的 HLL 合成一个再计数
- 搜索词覆盖量:统计某个关键词被多少个不同用户搜索过
- 广告触达人数:按素材或渠道统计不重复触达的设备数
- 大规模去重校验:在成本敏感的场景替代精确 Set,用可控误差换取内存数量级的节省
统计与合并
统计与合并
redis-cli PFADD uv:20261012 user100 user101 user102 # 记录访问用户
redis-cli PFCOUNT uv:20261012 # 当日去重人数(近似)
redis-cli PFADD uv:20261012 user100 # 重复元素不会改变计数
redis-cli PFMERGE uv:week uv:20261011 uv:20261012 # 合并成周维度
redis-cli PFCOUNT uv:week # 周去重人数
redis-cli PFCOUNT uv:20261011 uv:20261012 # 直接多键合并计数(开销更高)
redis-cli MEMORY USAGE uv:20261012 # 观察固定内存占用与精确去重的取舍
| 方案 | 内存 | 精度 |
|---|---|---|
| Set | 与元素数成正比,百万元素即数十 MB | 精确,可取回全部成员 |
| HyperLogLog | 固定约 12KB | 标准误差约 0.81%,无法枚举成员 |
| Bitmap | 与最大编号成正比 | 精确,但要求对象编号稠密 |
| Sorted Set 去重 | 开销高于 Set | 精确且有序,代价最高 |
PFCOUNT 对单个键是近似常量时间的,但传入多个键时服务端需要临时合并这些结构再进行估算,开销明显更高,且会更新内部缓存。高频大合并的正确做法是先 PFMERGE 到一个目标键,再对该键做 PFCOUNT。
结果波动是算法特性而非故障:同一组数据在不同合并顺序下可能得到略有差异的估算值。对账场景应在协议里预留误差区间,或改用能给出精确值的结构承载对账。