HyperLogLog 比 Set 节省约三个数量级内存,100 万唯一元素下仅需约 12 KB,而 Set 需 15–25 MB;它不存原始值,仅用 16384 桶寄存器基于哈希前导零估算基数,误差率默认 0.81%。

HyperLogLog 比 Set 节省多少内存?
在 100 万唯一元素场景下,SET 通常占 15–25 MB,而 HyperLogLog 固定只用约 12 KB——不是“略少”,是差三个数量级。它不存原始值,只维护一个 16384 桶的稀疏概率寄存器,靠哈希值前导零位数做基数估算。
- 误差率默认 0.81%,可接受时才用;要精确去重(比如发券防重复领取),不能用
-
PFADD插入、PFCOUNT查询,命令名带PF(Philippe Flajolet)不是随便起的 - 同一个 key 多次
PFADD相同值,自动去重,但底层不校验内容是否真相同,只看哈希结果
PFADD 插入失败或没生效?检查这三点
现象:反复调 PFADD 后 PFCOUNT 始终为 0 或不增长。常见不是命令写错,而是语义或环境问题。
- 传入空字符串或
null:Redis 把空串当有效元素,但某些客户端 SDK(如 Jedis 3.x)对null参数静默丢弃,不报错也不插入 - key 被其他逻辑覆盖:比如误用
SET写了同名 key,后续PFADD会失败并返回错误WRONGTYPE Operation against a key holding the wrong kind of value - 管道(pipeline)中混用命令:若在 pipeline 里先
DEL再PFADD,而中间有并发写入,可能因 key 被删导致PFADD初始化失败(部分旧版 Redis 返回 0)
从 SET 迁移到 HyperLogLog 的兼容陷阱
不能简单把 SADD user:active:202405 改成 PFADD user:active:202405——语义完全不同。
-
SET支持SMEMBERS查所有元素,HyperLogLog完全不支持反查;迁移前确认业务是否真需要“列出全部去重 ID” -
EXPIRE对两者都有效,但HyperLogLog的 key 即使过期也不会自动清理桶内状态(无影响,只是说明它真的只存统计摘要) - 如果原逻辑依赖
SCARD返回精确值,替换后得同步改业务代码容忍 ±0.81% 误差,比如“日活 ≥ 100 万”判断要改成 ≥ 992000
什么时候不该用 HyperLogLog?
它不是万能压缩方案,硬套反而埋坑。
- 元素量级太小(HyperLogLog 固定 12 KB,而小
SET可能只占几百字节,此时更费内存 - 需要交集/并集:
PFMERGE只支持并集,不支持交集、差集;想算“今天登录且昨天登录的用户”,得回退到SET或用布隆过滤器组合 - 元素本身是长字符串(如 URL):虽然不影响功能,但哈希计算开销略升,高频写入时 CPU 使用率比短 key 明显高
真正省空间的前提是:你只要“大概有多少个”,且这个“大概”业务上能兜住。否则宁可多花几 MB,别为省内存把逻辑搞复杂。

















