Redis HyperLogLog

HyperLogLog是一种用于基数统计的概率数据结构,本课学习HyperLogLog的使用。

什么是HyperLogLog?

HyperLogLog的特点:

💡 对比:

  • 使用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的场景

使用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。

📖 小节

📝 作业

  1. UV统计: 使用HyperLogLog统计网站每日UV,模拟多个用户访问
  2. 多日统计: 创建多日的UV HyperLogLog,使用PFMERGE合并统计周UV
  3. 精度测试: 添加1000个不同元素,对比PFCOUNT结果与实际数量
  4. 对比测试: 对比使用Set和HyperLogLog统计相同数据的内存占用

下一课

下一课我们将学习 Redis 发布订阅,学习消息发布和订阅。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏