直接用 pfadd + pfcount 即可实现去重统计,关键在于按商品 id 粒度建独立 hll key(如 uv:product:10086:20260519),避免混用单 key;批量 pfadd、慎用多 key pfcount,千级规模下内存仅约 12mb,误差 0.81% 可接受。

直接用 PFADD + PFCOUNT 就能实现——关键不是“能不能用”,而是“怎么分 key”和“什么时候该停手”。千级商品群规模下,内存压力其实不大,但结构设计错了,1000 个商品就可能吃掉几 GB 内存。
按商品 ID 粒度建独立 HLL Key
每个商品一个 HyperLogLog,key 命名建议带业务前缀和时间维度,例如:
uv:product:10086:20260519(商品 10086 的今日 UV)
这样做的好处是:互不影响、可单独查询、可定时过期、合并灵活。
避免把所有商品 ID 拼进一个 key,比如 uv:all_products —— 一旦混入,PFCOUNT 就失去商品粒度,后续无法拆解,也丧失横向扩展能力。
单次 PFADD 支持批量,别循环调用
客户端应一次提交多个用户 ID,而不是对每个用户都发一条 PFADD:
- ✅ 正确:PFADD uv:product:10086:20260519 uid_123 uid_456 uid_789
- ❌ 错误:连续三次 PFADD,每次只传一个 uid
批量操作降低网络往返与 Redis 解析开销,千级商品 × 百万级日访问量时,QPS 压力差异明显。注意:PFADD 返回值为 1 表示该 uid 是首次被识别(非写入成功标志),不建议用它做业务逻辑判断。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
PFCOUNT 要慎用多 key 合并场景
如果要查「某类商品集合的总 UV」,比如「手机类目下 50 个热销商品的去重访客数」,不要手动 PFCOUNT 50 次再相加(会高估,因交集被重复计算):
- ✅ 推荐:先用 PFMERGE 生成临时聚合 key,再 PFCOUNT 一次
- ✅ 更优:预设类目级 HLL,如 uv:category:phone:20260519,由上游写入时同步 PFADD 两份(商品级 + 类目级)
注意 PFMERGE 不会修改源 key,只是读取后合并到目标 key,适合离线或准实时聚合。
千级规模下,不必强上分片或降精度
1000 个商品 × 每个日均 10 万 UV ≈ 总计 1 亿去重 ID;HyperLogLog 每个 key 固定约 12KB 内存,1000 个 key 仅占 ~12MB,远低于 SET 方案可能消耗的数百 MB~GB 级别。
此时无需开启稀疏编码、也不必调低精度参数(如调整 register 数量)。标准误差 0.81% 完全可接受——10 万真实 UV,误差 ±810,业务感知微弱。真需要精确值的场景(如结算、审计),应另走日志+离线计算链路,而非在 Redis 里硬扛。










