Redis HyperLogLog 基数统计
统计"集合里有多少个不重复元素"叫基数统计,例如网站每日独立访客数(UV)。数据量大时,把每个 ID 存进 Set 再求个数会占用大量内存。HyperLogLog(HLL)用极小且固定的内存完成基数统计,标准误差约 0.81%,是"用一点误差换海量内存"的典型结构。
基本命令
PFADD 添加元素,PFCOUNT 返回去重后的近似数量:
PFADD uv:20240601 u1001 u1002 u1003
# 输出:(integer) 1 # 内部寄存器有变化
PFADD uv:20240601 u1001
# 输出:(integer) 0 # 重复元素,寄存器无变化
PFCOUNT uv:20240601
# 输出:(integer) 3 # 近似值,误差约 0.81%
去重依据的是元素"值本身",不要求元素预先登记,同一元素重复添加不会增加基数。
内存占用
无论往一个 key 里塞 1 个还是上亿个元素,单 key 内存上限约 12KB(元素很少时实际占用更小),这是它相对 Set 的最大优势——Set 存 1000 万个 ID 往往要几十 MB。代价是无法取出元素、也无法精确计数。
多日并集:PFCOUNT 与 PFMERGE
PFCOUNT 可一次传多个 key 直接返回并集基数;PFMERGE 把多个 key 合并进一个新 key,适合把"每日 UV"汇总成"周 UV、月 UV":
PFADD uv:20240601 u1001 u1002
# 输出:(integer) 1
PFADD uv:20240602 u1002 u1003
# 输出:(integer) 1
PFCOUNT uv:20240601 uv:20240602
# 输出:(integer) 3 # 两天去重后约 3 人
PFMERGE uv:week uv:20240601 uv:20240602
# 输出:OK
PFCOUNT uv:week
# 输出:(integer) 3 # 周 UV 与两日并集一致
合并完成后源 key 即可删除,只保留汇总 key,跑日报/周报定时任务时很省事。
典型场景
- 网站/App 日活 UV:一天一个 key,访问时 PFADD,日切后 PFCOUNT。
- 搜索词去重、直播间独立观众、活动参与人数等"看量级和近似值"就够的统计。
- 需要精确到个位、或要回查"某元素是否在其中"时不要用 HLL:精确计数用 Set/位图,存在性判断用布隆过滤器。
注意点
- 返回近似数,对账、计费等对 0.81% 误差敏感的业务不可用。
- 只支持添加、不支持删除单个元素,写错只能整体重建 key。
- 基数很小时误差可能表现为 0,但不要据此认为它精确。
小结
HyperLogLog 用约 12KB 级固定内存换取近似基数统计,误差 0.81%,命令只有 PFADD / PFCOUNT / PFMERGE 三个。UV、去重统计这类量大但允许小误差的场景,是它的主场。