redis hyperloglog 是千万级 uv 统计最优解,12kb 内存支持 2⁶⁴ 量级去重估算,误差±0.81%;pfadd 返回值表新元素识别而非操作成败,pfcount 多key为实时并集估算,不修改源key但耗cpu;需按天分key、分业务域使用,无法精确回溯。

Redis HyperLogLog 是目前最实用的千万级 UV 统计方案,只要用对 PFADD,12 KB 内存就能撑住 2⁶⁴ 量级的去重估算,误差稳定在 ±0.81%。它不存原始数据,不能查具体是谁,但正因如此才轻量、可合并、适合高并发写入。
PFADD 怎么用才不会漏统计或误判返回值
PFADD 的返回值不是“成功/失败”,而是“是否有新元素被识别为首次出现”。这点极易误解:
- 返回
1:至少有一个参数是该 HyperLogLog 之前没见过的(哪怕只加一个新元素,其余全是重复,也返回 1) - 返回
0:所有参数都已被该结构“记住”过(注意:不是网络失败,也不是命令报错) - 不校验参数类型——传空字符串
""、数字123、JSON 字符串"{\"id\":1}"都合法,但必须保证业务上能唯一标识用户(比如用user_id或device_id,别用 session_id 这种短期值) - 单次最多支持 1024 个元素;超了得拆成多条命令,否则会截断(redis-py 默认会自动分片,但原生命令行或低版本客户端不会)
PFCOUNT 多 key 合并时的隐含行为
调用 PFCOUNT key1 key2 key3 实际等价于先执行一次内存中临时 PFMERGE,再对合并结果做基数估算。这不是简单相加,而是并集去重后的估算:
- 如果
key1和key2有大量重叠用户,PFCOUNT key1 key2结果会显著小于PFCOUNT key1+PFCOUNT key2 - 合并过程不修改任何源 key,纯读操作,安全;但高并发下频繁多 key
PFCOUNT可能引发短暂 CPU 尖峰(因需实时合并哈希结构) - 线上建议:日常用单 key
PFCOUNT查分片结果;汇总类报表才用多 key 合并,且避开流量高峰
千万 UV 场景下 PFADD 的实际吞吐与稳定性要点
真实压测表明,单实例 Redis(4 核 8G)在 pipeline 模式下,PFADD QPS 轻松突破 5 万+。但要注意三个硬约束:
- 每个 HyperLogLog 固定占 12 KB 内存,不管里面是 1 个还是 1 亿个用户;所以按天建 key(如
uv:20260401)比长期复用一个 key 更利于内存管理 - 不要把不同业务域混进同一个 key——比如把 PC 端和 App 端的
user_id往同一个uv:20260401里塞,会导致跨端重复用户被错误去重 - 若需精确回溯(例如“今天新增 UV 中有多少来自微信渠道”),
PFADD本身做不到,得配合 Bitmap 或单独记录日志;HyperLogLog 只负责“总数快、内存省、合并易”这一件事
真正容易被忽略的是:HyperLogLog 的误差是系统性的,不是随机漂移。连续两天 PFCOUNT 出来都是 992 万,不代表真实 UV 就是这个数——它只是告诉你,大概率在 984 万~1000 万之间(按 0.81% 误差反推)。需要这个精度就用,要精确值就换方案。










