首页/数据/数据库速查/去重方案对比(Set/Bitmap/HLL/Bloom)
Redis 运维与场景124 条

去重方案对比(Set/Bitmap/HLL/Bloom)

按「要不要判断单个元素存在 + 精度 + 内存」选去重结构:Set 精确但费内存、Bitmap 适合稠密整数 ID、HLL 近似基数、布隆过滤器可判定存在但有误判。

数据库速查数据更新于 2026-10-13

按需求选去重结构

去重方案的选择取决于三件事:是否需要判断单个元素是否存在、能接受多大误差、内存预算是多少。Set 精确但每个元素都有固定开销,Bitmap 适合稠密整数 ID,HyperLogLog 只输出近似基数且单键固定约 12KB,布隆过滤器能判断存在但存在误判。组合使用往往比单一方案更划算。

方案对比

方案精确性内存适用
Set精确大,每个元素都有开销中小基数且需要判断成员是否存在
Bitmap精确与最大 ID 成正比稠密连续的整数 ID
HyperLogLog近似,约 0.81% 误差每键不超过约 12KBUV 类基数统计
Bloom存在判定有误判小拦截不存在的查询与重复提交
Hash 计数精确中等需要记录出现次数的场景

四类命令对照

四类命令对照
SADD dedup:order:2026 O1 O2      # 精确:成员去重
SISMEMBER dedup:order:2026 O1     # 精确:判断是否已存在
SETBIT ua:20261012 1001 1         # 位图:适合稠密整数 ID
BITCOUNT ua:20261012              # 位图:统计活跃数量
PFADD uv:20261012 u1001           # 近似基数:内存固定
PFCOUNT uv:20261012               # 近似基数:输出估算值
BF.ADD bloom:user u1001           # 布隆过滤器,需 RedisBloom 模块
BF.EXISTS bloom:user u1001        # 存在判定,可能误判为存在

典型使用场景

  • 订单号去重:精确判重且基数不大时用 Set
  • 日活统计:用户 ID 稠密连续时用位图
  • 报表 UV:只要量级时用 HyperLogLog 省内存
  • 重复提交拦截:布隆过滤器快速挡掉不存在的键
  • 多级组合:先用布隆挡住大部分请求,再用 Set 精确判重
组合拳示例:查询先过布隆过滤器拦掉不存在的数据,命中后再用 Set 精确判重;报表侧 UV 用 HyperLogLog,兼顾内存与量级。
用 HyperLogLog 判断某个元素是否出现过是行不通的:它只提供基数估算,不支持单元素查询,需要成员判定就必须换结构。

落地顺序建议

  • 先确认是否需要成员查询:不需要时优先考虑基数统计类结构
  • 再在精确与内存之间取舍,量级越大越应倾向近似方案
  • 布隆过滤器可能把不存在的元素判为存在,业务侧仍需精确校验兜底
  • 去重键统一设置过期时间,避免按天累积后内存持续上涨

易错点

  • 用 HyperLogLog 做单元素存在判断:它不支持这类查询,功能上根本做不到
  • 用稀疏的超大 ID 建位图:内存按最大 ID 分配,个别大号就能把键撑到很大
  • 把布隆过滤器的结果当精确判定:误判会导致合法元素被拒,业务侧要有兜底路径
  • 去重键不设过期:按天累积的键越来越多,内存长期缓慢增长

数据来源与参考

  • Redis 官方文档: 数据类型
  • RedisBloom 文档

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌