首页/数据/Redis 进阶速查/HyperLogLog 基数统计
数据结构与选型42 条

HyperLogLog 基数统计

用约 12KB 固定内存估算集合基数,标准误差约 0.81%,适合 UV、去重计数等场景;PFADD 写入、PFCOUNT 读取、PFMERGE 合并。

Redis 进阶速查数据更新于 2026-10-13

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。
结果波动是算法特性而非故障:同一组数据在不同合并顺序下可能得到略有差异的估算值。对账场景应在协议里预留误差区间,或改用能给出精确值的结构承载对账。

易错点

  • 用 HyperLogLog 做需要精确金额或精确人数的结算,误差会直接体现为对不上账,精确统计必须用 Set 或其他结构
  • 需要查明细时才发现取不回成员:HLL 只给基数,任何「查是谁访问的」需求都要另建明细表或 Set
  • 把每个维度都建独立 HLL 且长期不设过期,键数量膨胀带来可观的内存总量,应按分析周期设置 TTL
  • 反复对大量键执行多键 PFCOUNT 而不先合并,每次调用都触发内部计算,CPU 开销远高于预期

数据来源与参考

  • Redis 官方文档:HyperLogLog 数据类型
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌