Sunday面试指南

Redis HyperLogLog 怎么统计 UV?为什么不能查询成员,也不能直接删除用户?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:每天有很多访客,你会用 Redis 怎样统计 UV?

🙋‍♂️ 我:把用户放进 HyperLogLog,空间小,也能去重。

🧑‍💻 面试官:那能从里面查出今天有哪些用户吗?一个用户要求撤回记录,能只删他吗?

🙋‍♂️ 我:不能把它当成保存完整成员的 Set。

🧑‍💻 面试官:把每天 UV 相加,就是一周 UV 吗?所谓 0.81% 误差,是不是保证每次都不超过这个值?

HyperLogLog 保存的是「估算人数的摘要」,不是一份可以逐个查看、逐个删除的访客名单。

面试速答(60 秒版)

HyperLogLog 是近似基数统计结构,适合估算有多少不同元素。例如把统一身份口径的访客标识加入同一天的结构,再取得近似 UV。

Redis 中可以用 PFADD 加入元素、PFCOUNT 取得估计数量、PFMERGE 合并多个结构,估算它们的并集。合并周 UV 时不能直接相加每日结果,因为同一用户可能多天出现。

它利用哈希统计摘要节省空间,不保存可供列举的完整成员,所以不能据此判断某个具体用户是否访问,也不能直接逐个删除成员。

Redis 文档给出的 0.81% 是标准误差,不是每次估计绝对误差的硬上限。需要准确名单、精确结算或成员删除时,应该选择具有相应语义的存储,而不是因为节省内存就强用 HLL。

要人数,还是要名单?

知识点详解:从访客名单,换成一份计数摘要

UV 的“不同”,先由身份口径决定

假设用户 u1 访问三次,u2 访问一次。如果按登录用户 ID 去重,这两人产生两份独立身份,而不是四个 UV。

但同一个人未登录时使用多个设备标识,可能被统计成多个身份;多人共享一个标识,也可能被合并。HyperLogLog 不会替我们识别人类的真实身份。

因此,先定义按用户、设备还是匿名标识去重,确定站点、页面和时间范围,再把一致标识加入结构。输入口径错了,换一种更精确的数据结构也救不了指标。

Set 留名字,HyperLogLog 留统计特征

使用 Set,可以保存 u1、u2,支持精确成员判断和枚举;随着不同成员增多,需要保存的成员信息也增加。

HyperLogLog 先把输入哈希化,再将哈希的一部分用于选择统计位置,另一部分用于记录相应的特征,例如特定位模式出现的程度。整体特征用于估算基数。

同一输入通常贡献同样的特征,所以重复加入不相当于增加一位新访客;不同输入也不保证每次都改变摘要,因为它们可能没有提高相关统计位置已有的记录。

Redis HLL 文档介绍了空间与准确率的取舍。重点不是把所有哈希公式背出来,而是理解:我们用摘要换掉了完整名单。

留下统计特征,不留下每个名字

三条命令,分别负责什么?

下面是 Redis 命令示例,应在独立测试实例和专用测试键执行:

PFADD uv:demo:day1 u1 u2 u1
PFCOUNT uv:demo:day1

PFADD uv:demo:day2 u2 u3
PFMERGE uv:demo:two-days uv:demo:day1 uv:demo:day2
PFCOUNT uv:demo:two-days

第一天观察到的是 u1、u2,第二天是 u2、u3。两天并集的实际不同输入有三个,而不是每日数量相加得到的四个。

HLL 返回的是估计值,小规模示例可能得到精确结果,但不能由此推导大规模统计必然精确。

PFADD的返回值表示内部结构是否变化,不是“这次增加了几名 UV”。PFCOUNT 才用于取得基数估计。

周 UV 为什么应该合并结构,而不是合计数字?

每天的结果只保留一个估计数量。周统计需要知道跨天重复关系,但单独的数字没有这份信息。

PFMERGE 按摘要规则形成并集的统计结构,然后再取估计值。PFMERGE 文档说明了并集含义,而不是算术相加。

还有一个实际边界:如果目标键已经存在,它的原内容也会参与合并。想得到指定日期范围的快照时,应使用明确的新目标或符合更新语义的目标,不要把历史超范围摘要误混进来。

HLL 支持这种并集,并不意味着可以从两份计数中直接恢复交集名单,或者精确做减法。

周 UV,不能把每天人数相加

0.81% 和 12 KB,怎样说才准确?

Redis 文档给出的约 0.81% 是标准误差,用于描述估计精度,不是“无论怎样输入,每一次都保证误差不超过 0.81%”。

类似地,常见“最多约 12 KB”主要说 HLL 摘要空间这一层,不包含整个 Redis 中键名、元数据、复制及大量键的总开销。

如果按每个页面、每个小时都建一个结构,总键数仍然可能很大。不能用“一个 HLL 小”推导整个统计系统不需要容量规划。

删除某个用户,为什么不能靠减一?

结构里没有完整名单,也没有每个用户独立的一格贡献。

一个用户多次出现、多个用户共享统计特征,都会使“撤掉这个用户的贡献”无法简单反推。把估计数量减一,既没有修改原摘要,也不能让后续重新统计得到可靠结果。

有删除需求时,可以保留符合隐私策略和保留期限的权威数据,在需要时重新构建;如果业务本来就要求精确成员操作,则应选合适的集合或数据库方案。

滚动窗口也不能简单让一个周 HLL 每天“减掉昨天”。可以按固定时间桶保存,再合并当前需要的桶;粒度、误差和过期时间仍要明确。

面试官继续追问

HLL 能判断这个用户来过吗?

不能提供成员查询语义。布隆过滤器是另一类结构,也有误判边界;不能用 HLL 代替它。

计费人数可以直接用 HLL 吗?

如果结算要求精确且可审计,不能只靠近似摘要。近似流量看板和权威结算是不同任务。

身份是数字,用 Bitmap 就一定更省吗?

要看编号范围和稀疏程度。很大的稀疏编号可能浪费空间,且 Bitmap 保存具体位的语义与 HLL 估算也不同。

面试速记卡

  • 用途:估算不同元素数量,先确定身份与时间口径。
  • 数据:哈希统计摘要,不是完整访客名单。
  • 命令:PFADD 更新,PFCOUNT 估计,PFMERGE 合并并集。
  • 精度:0.81% 是标准误差,不是单次误差硬上限。
  • 边界:不做成员查询、逐个删除或精确结算;跨天不能直接加数量。

公司面试真题

这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历