什么是HyperLogLog?
HyperLogLog 是 Redis 提供的一种概率数据结构,专门用于估算海量数据中不同元素的数量。它用固定的12KB内存,就能估算最多184亿亿(2^64)个不同元素,误差率仅0.81%。
1. 格式
# 基础语法
PFADD key value1 value2 ...
# 示例
PFADD video:views:123 "user1" "user2" "user3"
2. 特点
- 元素类型不限:value支持中文、英文、数字、长文本等任意类型
- 理论容量极大:每个key最多估算约184亿亿个不同元素
- 存储方式特殊:元素被哈希成64位二进制,不存储原始数据
- 内存占用固定:每个key固定约12KB,与元素数量无关
- 结果是估算值:基于概率算法,不是精确计数
简单的比喻
HyperLogLog就像:
- 看沙滩上的脚印估算来了多少人
- 看停车场停了多少车估算商场客流量
- 看朋友圈点赞头像数估算你的朋友数量
看具体命令怎么用
假设你是抖音,要统计某个视频,比如视频888,视频999的观看人数,
# 1. 记录用户观看(用户张三看了视频888)
PFADD video:views:888 "user_zhangsan"
# 2. 再记录几个用户(李四、王五)也看了视频888
PFADD video:views:888 "user_lisi"
PFADD video:views:888 "user_wangwu"
PFADD video:views:888 "user_zhangsan" # 同一个人又看了一次
# 3. 问:这个视频有多少不同的人看过??
PFCOUNT video:views:888
# 返回:3 (user_lisi,user_wangwu各1次,user_zhangsan看了2次但只算1次)
# 4. 另一个视频999的数据
PFADD video:views:999 "user_zhangsan"
PFADD video:views:999 "user_999"
# 5. 问:视频888和999一共被多少不同的人看过?
PFMERGE total_views video:views:888 video:views:999
PFCOUNT total_views
# 返回:4(user_zhangsan,user_lisi,user_wangwu,user_999)
为什么要用HyperLogLog?
情况1:用普通方法(Set集合)
# 记录1亿用户观看
SADD video:views:888 "user1" "user2" ... "user100000000"
# 内存占用:约800MB!
# 统计:SCARD video:views:888 (精确)
# 问题:一个视频就占800MB,100个视频就80GB,太贵了!
情况2:用HyperLogLog
# 记录同样的1亿用户观看
PFADD video:views:888 "user1" "user2" ... "user100000000"
# 内存占用:永远只需要12KB!
# 统计:PFCOUNT video:views:888 (估算)
# 优势:1个视频12KB,100个视频也才1.2MB!
什么时候该用它?
✅ 适合用的场景:
-
网站统计UV(独立访客)
- 每天有100万人访问,你只想知道大概人数
- 不关心具体是谁访问了
-
APP的日活用户
- 想知道今天大概有多少人打开了APP
- 差几百人的误差没关系
-
广告点击去重
- 一个用户点了10次广告,只算1次有效点击
- 广告主接受少量误差
❌ 不适合用的场景:
-
银行账户统计
- 不能说"您账户大概有10000元,误差±81元"
-
选举投票统计
- 不能说"候选人A大概得了10000票,误差±81票"
-
需要知道具体有哪些人的场景
- 比如发优惠券给所有参与的用户
误差到底有多大?
# 例子:
PFADD mydata 几百万个用户ID...
PFCOUNT mydata
# 可能结果:
真实人数:1,000,000人
HyperLogLog返回:992,000 ~ 1,008,000人
误差率:0.81%
# 也就是说:
100万人 → 可能少算8100人或多算8100人
1000万人 → 可能少算8.1万人或多算8.1万人
实际应用对比
场景:统计公众号文章阅读人数
| 方法 | 内存消耗 | 精确度 | 能否知道谁读了 |
|---|---|---|---|
| 记录所有用户ID | 很大(用户越多越大) | 100%精确 | 可以,知道每个读者 |
| HyperLogLog | 固定12KB | 约99.19%精确 | 不能,只知道大概人数 |
一句话总结
HyperLogLog就是:
用很小的固定空间(12KB),快速估算超大数据集中有多少个不同的东西,牺牲一点精确度(0.81%误差),换来巨大的内存节省。
那么问题来了
为什么我刚刚举例的视频888,视频999的观看人数,pfcount之后得到的结果是精准的,并没有0.81%的误差?
这是理解HyperLogLog的关键点,数据量小的时候,HyperLogLog可能是准确的!
为什么小数据量时准确?
原因1:小数据时HyperLogLog会自动使用精确算法
- Redis的HyperLogLog在数据量小时使用精确计数
- 数据量超过某个阈值(约30000)才切换为概率估算
- 这是优化策略,避免"大炮打蚊子"
原因2:0.81%是最大误差,不是每次都有误差
- 误差是概率性的,不是固定的,好比投硬币,正面朝上的概率50%,不代表每投2回就有一回是正面朝上
记住这个选择:
- 数据量大,只要大概数量,不关心具体是谁 → 用HyperLogLog
再看一个完整例子
# 假设你是微博,要统计热搜话题的阅读人数
# 方法1:精确统计(太占内存)
# 每个阅读用户都记录:user1, user2, user3...
# 1000万人阅读 → 可能需要几百MB内存
# 方法2:用HyperLogLog(省内存)
# 同样1000万人阅读 → 只需要12KB内存
# 结果:"这个话题大约有992万~1008万人阅读"
# 选择:
# - 如果是给广告商看数据 → 用HyperLogLog(可以接受误差)
# - 如果是给财务算钱 → 不能用HyperLogLog(必须精确)
HyperLogLog就是估算神器,专门解决"大概有多少个不同的东西"这个问题,特别省内存!