Redis HyperLogLog
HyperLogLog是一种用于基数统计的概率数据结构,本课学习HyperLogLog的使用。
什么是HyperLogLog?
HyperLogLog的特点:
- 基数统计:统计不重复元素的数量
- 占用内存极小:每个HyperLogLog只占用12KB内存
- 近似统计:标准误差约0.81%,适合大规模数据
- 不存储元素本身:只存储统计信息
💡 对比:
- 使用Set统计:需要存储所有元素,内存占用大
- 使用HyperLogLog:只占用12KB,但结果是近似值
Set: 存储100万个不同元素 → 约10MB内存
HyperLogLog: 统计100万个不同元素 → 仅12KB内存
PFADD:添加元素
基本用法
REDIS
# 添加单个元素
PFADD uv:20260623 "user:1"
(integer) 1 # 返回1表示基数可能变化
# 添加多个元素
PFADD uv:20260623 "user:2" "user:3" "user:4"
(integer) 1
# 添加已存在的元素
PFADD uv:20260623 "user:1"
(integer) 0 # 返回0表示基数未变化
自动去重
REDIS
# HyperLogLog自动去重
PFADD uv:20260623 "user:1" "user:1" "user:2"
(integer) 0 # user:1已存在,只有user:2是新的
⚠️ 注意: HyperLogLog不存储元素本身,只更新内部统计信息。无法获取具体元素列表。
PFCOUNT:获取基数
REDIS
PFADD uv:20260623 "user:1" "user:2" "user:3" "user:4"
# 获取不重复元素数量
PFCOUNT uv:20260623
(integer) 4
# 添加重复元素
PFADD uv:20260623 "user:1" "user:5"
# 基数增加1(user:5)
PFCOUNT uv:20260623
(integer) 5
统计多个HyperLogLog的并集基数
REDIS
# 创建多个HyperLogLog
PFADD uv:20260622 "user:1" "user:2" "user:3"
PFADD uv:20260623 "user:2" "user:3" "user:4"
# 统计两天的UV并集
PFCOUNT uv:20260622 uv:20260623
(integer) 4 # user:1, user:2, user:3, user:4
💡 用途: PFCOUNT可以统计多个HyperLogLog的并集基数,无需先合并。
PFMERGE:合并HyperLogLog
PFMERGE将多个HyperLogLog合并为一个。
基本用法
REDIS
# 创建多个HyperLogLog
PFADD uv:20260622 "user:1" "user:2"
PFADD uv:20260623 "user:2" "user:3"
PFADD uv:20260624 "user:3" "user:4"
# 合并到新的HyperLogLog
PFMERGE uv:week uv:20260622 uv:20260623 uv:20260624
OK
# 查看合并后的基数
PFCOUNT uv:week
(integer) 4 # user:1, user:2, user:3, user:4
合并到已存在的HyperLogLog
REDIS
# 合并到已存在的HyperLogLog(覆盖)
PFMERGE uv:20260622 uv:20260623
OK
PFCOUNT uv:20260622
(integer) 3 # user:1, user:2, user:3
HyperLogLog应用场景
场景1:网站UV统计
REDIS
# 每日UV
PFADD uv:daily:20260623 "user:1"
PFADD uv:daily:20260623 "user:2"
PFADD uv:daily:20260623 "user:3"
# 查看今日UV
PFCOUNT uv:daily:20260623
(integer) 3
# 每周UV
PFMERGE uv:weekly:2026w25 uv:daily:20260617 uv:daily:20260618 ... uv:daily:20260623
PFCOUNT uv:weekly:2026w25
场景2:文章阅读人数统计
REDIS
# 文章阅读人数
PFADD article:123:readers "user:1"
PFADD article:123:readers "user:2"
PFADD article:123:readers "user:3"
# 查看阅读人数
PFCOUNT article:123:readers
(integer) 3
场景3:搜索关键词统计
REDIS
# 今日搜索关键词(不重复)
PFADD search:keywords:20260623 "redis"
PFADD search:keywords:20260623 "mysql"
PFADD search:keywords:20260623 "redis"
# 查看不重复关键词数量
PFCOUNT search:keywords:20260623
(integer) 2
场景4:在线人数统计
REDIS
# 当前在线用户
PFADD online:users "user:1"
PFADD online:users "user:2"
PFADD online:users "user:3"
# 查看在线人数
PFCOUNT online:users
(integer) 3
# 用户下线(需要重建HyperLogLog,较麻烦)
# HyperLogLog不支持删除单个元素
场景5:API调用统计
REDIS
# API调用用户统计
PFADD api:users:get:user 1001
PFADD api:users:get:user 1002
PFADD api:users:get:user 1003
# 查看调用用户数
PFCOUNT api:users:get:user
(integer) 3
HyperLogLog vs Set对比
内存占用对比
| 数据量 | Set内存 | HyperLogLog内存 |
|---|---|---|
| 1万 | ~800KB | 12KB |
| 10万 | ~8MB | 12KB |
| 100万 | ~80MB | 12KB |
| 1000万 | ~800MB | 12KB |
💡 结论: HyperLogLog内存占用恒定为12KB,与数据量无关。
精度对比
| 数据结构 | 精度 | 适用场景 |
|---|---|---|
| Set | 精确 | 需要精确统计、需要获取元素列表 |
| HyperLogLog | 近似(误差0.81%) | 大规模数据、只需要基数、内存敏感 |
功能对比
| 功能 | Set | HyperLogLog |
|---|---|---|
| 添加元素 | ✅ SADD | ✅ PFADD |
| 删除元素 | ✅ SREM | ❌ 不支持 |
| 获取元素列表 | ✅ SMEMBERS | ❌ 不支持 |
| 检查元素存在 | ✅ SISMEMBER | ❌ 不支持 |
| 获取基数 | ✅ SCARD | ✅ PFCOUNT |
| 合并 | ✅ SUNIONSTORE | ✅ PFMERGE |
HyperLogLog精度测试
测试代码
REDIS
# 添加100万个不同元素
for i in range(1000000):
PFADD test:hll f"user:{i}"
# 查看统计结果
PFCOUNT test:hll
(integer) 1000123 # 略微偏离,误差约0.012%
ℹ️ 了解: HyperLogLog标准误差约0.81%,实际误差通常更小。
HyperLogLog限制
1. 无法删除元素
REDIS
# HyperLogLog不支持删除单个元素
# 如果需要删除,只能重建整个HyperLogLog
2. 无法获取元素列表
REDIS
# HyperLogLog不存储元素本身
# 无法像Set那样使用SMEMBERS获取所有元素
3. 结果是近似值
REDIS
# HyperLogLog返回的是近似基数
# 不是精确值,有约0.81%的误差
4. 无法检查元素是否存在
REDIS
# HyperLogLog不支持检查某个元素是否存在
# 无法像Set那样使用SISMEMBER
何时使用HyperLogLog?
使用HyperLogLog的场景
- 统计网站UV(独立访客)
- 统计文章阅读人数
- 统计搜索关键词数量
- 统计API调用用户数
- 大规模数据基数统计
- 内存敏感的场景
使用Set的场景
- 需要精确统计
- 需要获取元素列表
- 需要删除元素
- 需要检查元素是否存在
- 数据量较小
❓ 常见问题
Q HyperLogLog的误差有多大?
A 标准误差约0.81%。对于100万数据,误差约8000左右。实际误差通常更小。
Q HyperLogLog占用多少内存?
A 每个HyperLogLog固定占用12KB内存,与数据量无关。
Q HyperLogLog能存储多少元素?
A 理论上无限制(2^64),但实际受精度影响。数据量越大,相对误差越小。
Q 如何删除HyperLogLog中的元素?
A 不支持。只能删除整个HyperLogLog(DEL命令)或重建。
Q HyperLogLog和Set如何选择?
A 需要精确统计或获取元素列表用Set,大规模数据基数统计用HyperLogLog。
📖 小节
- HyperLogLog用于基数统计,内存占用恒定12KB
- PFADD添加元素,自动去重
- PFCOUNT获取基数,可统计多个HyperLogLog的并集
- PFMERGE合并多个HyperLogLog
- 标准误差约0.81%,适合大规模数据
- 无法删除元素、无法获取元素列表、结果是近似值
- 应用场景:UV统计、阅读人数、搜索关键词、在线人数
📝 作业
- UV统计: 使用HyperLogLog统计网站每日UV,模拟多个用户访问
- 多日统计: 创建多日的UV HyperLogLog,使用PFMERGE合并统计周UV
- 精度测试: 添加1000个不同元素,对比PFCOUNT结果与实际数量
- 对比测试: 对比使用Set和HyperLogLog统计相同数据的内存占用
下一课
下一课我们将学习 Redis 发布订阅,学习消息发布和订阅。



