[TOC] #### 1. HyperLogLog --- UV 是 Unique Visitor(独立访客) 的缩写,在网站或 App 的运营中,我们通常关注两个指标: + PV(Page View,页面浏览量):用户每刷新或打开一次页面,PV 就加 1。同一个用户刷新了 10 次,PV 就是 10 + UV(Unique Visitor,独立访客数):统计一天内有多少个用户访问了页面。同一个用户刷新了多少次,UV 都只算 1 需求:你有一篇文章,想知道今天有多少独立用户看了 用 Set 能做:每个用户访问就 sadd 一下,最后 scard 统计数量,但 UV 到了千万级,Set 至少占几百 MB 内存 有没有更省空间的方案 ? 有。HyperLogLog,12KB 就能统计 2^64 个不同元素,代价是 0.81% 的误差率,而且不能查具体有哪些用户 对 UV 统计来说,够用了 基本操作 ```bash pfadd page:1001:uv user_001 pfadd page:1001:uv user_002 pfadd page:1001:uv user_001 # 重复,自动去重 pfcount page:1001:uv # 获取数量,输出结果:2 ``` 合并多个: ```bash pfmerge total:uv page:1001:uv page:1002:uv pfcount total:uv ``` pfadd 添加、pfcount 统计、pfmerge 合并,这三个命令就够用了 和 Set 对比,100 万 UV: + Set → 至少 50MB + HyperLogLog → 12KB 差了 4000 倍。但 HyperLogLog 不能告诉你具体有哪些用户,只能告诉你 “大概有多少个” 原理(简单版,不用背): + 对每个元素做哈希,看哈希值前导零的个数 + 连续出现的前导零越多,说明样本量越大 + 16384 个桶分别统计,取调和平均数,得到最终估算值 不用记细节,面试知道 “概率估算,0.81% 误差,12KB 固定内存” 就够了 #### 2. 实战:全站 UV --- 每天一个 HyperLogLog,月底合并: ```bash pfadd site:uv:20260501 user_001 user_002 pfadd site:uv:20260502 user_002 user_003 pfmerge site:uv:2026:05 site:uv:20260501 site:uv:20260502 pfcount site:uv:2026:05 # 获取数量,输出结果:3(user_002 自动去重) ``` 什么时候不用 HyperLogLog ? + 需要知道具体用户列表 → 用 Set + 数据量很小 → 用 Set,没必要上 HyperLogLog + 要求绝对精确 → 用 Set #### 3. 本文小结 --- 小总结: + HyperLogLog 统计去重数量,误差 0.81% + 固定 12KB,不管数据量多大 + pfadd 添加,pfcount 统计,pfmerge 合并 + 不能查具体元素,只能查数量 + UV 统计首选,量小或要精确用 Set