news 2026/4/15 12:02:41

美团二面挂了!问 “2亿日活怎么算”,我答 “Set集合”,面试官:你是想把 Redis 炸了吗?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
美团二面挂了!问 “2亿日活怎么算”,我答 “Set集合”,面试官:你是想把 Redis 炸了吗?

写在开头

昨天帮一位粉丝复盘美团二面,他说自己最委屈的是倒在了“Redis 海量数据统计”上。他在现场和面试官经历了这样一段“死亡对话”:

面试官推了推眼镜:“我们现在的 App 有 2 亿注册用户,大促期间预计有 1 亿用户登录。如何设计 Redis 存储方案来统计今天的日活(DAU),并支持快速判断某个用户是否登录?

老哥心里暗喜(这题我会啊): “这简单,用Set 集合!用户登录一个SADD一个,利用 Set 的去重特性,最后SCARD一下就是日活。”

面试官冷笑了一声: “那你知道存 1 亿个用户 ID(假设是 Long 类型),Set 需要消耗多少内存吗?Redis 单线程处理这么大的 BigKey,扩容和持久化时会发生什么?

老哥当场懵了,支支吾吾答不上来。

这一刻他才明白,面试官考的根本不是 API 怎么调,而是你对“底层成本”怎么算。

在小数据量下 Set 确实方便,但到了亿级流量,这简直是生产事故。

今天咱们就把这道题拆透,用“计算逻辑”“大厂架构视角”告诉你,为什么顶级架构师在这类场景下都不单纯用 Set。

第一步:算“笨办法”成本,揭露 Set 的致命陷阱

咱们先别急着写代码,先拿出计算器,算算朋友口中那个“简单”的 Set 方案。

假设用户 ID 是连续的 Long 类型,占 8 字节。

  • 你以为的内存:1 亿 × 8 字节 = 800 MB?错!大错特错!

  • 真实的 Redis 内存:Redis 的 Set 底层存储不仅存数据,还有dictEntryrobj等元数据开销,加上哈希表的负载因子导致的预分配。

在 64 位操作系统下,存储一个 Long 类型的字符串或数字,Set 内部每个元素平均大概需要50 - 64 字节的空间。

真实的账是这么算的:

结论:仅仅为了统计一天的日活,就要吃掉6.4G 内存

但这还不是最致命的。最致命的是你制造了一个核弹级的 BigKey:

  1. BigKey 阻塞:这是一个 6G 的巨型 Key,删除或过期时,主线程直接卡死;

  2. RDB 风险:生成快照时,fork 子进程复制页表,内存瞬间翻倍,甚至导致 OOM;

  3. 网络风暴:主从切换时,传输这个 6G 的 Key 会把网卡瞬间打满。

所以,Set 方案 = 生产事故

第二步:算“位图”优势,空间压缩 250 倍

看着面试官失望的眼神,这时候你必须祭出 Bitmap(位图)。

针对这种“只有 0 和 1 两种状态”(登录/未登录)的场景,Bitmap 是物理上的极致。它的底层是 String,但可以按 bit 操作。我们将用户 ID 作为 bit 的偏移量(offset),1 表示登录,0 表示未登录。

关键计算逻辑:

Bitmap 的大小不取决于“有多少人登录”,而取决于“最大的 UserID 是多少”。

题目中有 2 亿注册用户,假设 UserID 是连续的(1 ~ 200,000,000)。

对比冲击:

  • Set 方案:6.4 GB

  • Bitmap 方案:~24 MB

差距高达 250 倍以上!哪怕你要统计一整年的日活,Bitmap 加起来也不过 8GB 左右,完全在可控范围内。

第三步:生产环境的“进阶坑”,别忘分片

面试到这一步,如果你只答出 Bitmap,只能算“合格”。要拿“S card”,你得指出 Bitmap 的隐患:

单个 Bitmap 还是 BigKey 怎么办?

虽然 24MB 不算超大,但在高并发下,对同一个 Key 的频繁 SETBIT 操作(尤其是 Cluster 模式)会导致请求全部打向某一个分片(Slot),造成单点过热。

解法:分片(Sharding)。

将用户 ID 模 1000,拆分成 1000 个小的 Bitmap:

Key = dau:20251215:001

...

Key = dau:20251215:999

这样既打散了流量,又避免了单个 Key 过大。

注意:统计总数时,需要在应用层并发查询这 1000 个 Key 的 BITCOUNT 然后累加。

第四步:架构师视角(大厂是如何做日活统计的?)

如果面试官继续追问:“如果我的 ID 不是连续的数字,或者是雪花算法(Snowflake)生成的 19 位 ID 怎么办?老板想看北京地区的日活怎么办?”

这时候,Redis Bitmap 就不是银弹了。大厂通常采用“组合拳”

1. 稀疏 ID 场景 -> Roaring Bitmap

  • 痛点:如果 ID 是 19 位的,直接用 Redis Bitmap 会申请一段巨大的内存(PB级),中间全是 0,极度浪费。

  • 解法:使用Roaring Bitmap(压缩位图)。它在 Java 内存或大数据引擎中使用,对于稀疏数据,它使用数组存储;对于稠密数据,自动转换为位图。既省空间,又保留了位运算的高效。

2. 允许误差的大盘数据 -> HyperLogLog

  • 痛点:几千个业务线都要统计日活,内存还是不够用。

  • 解法Redis HyperLogLog。无论日活是 1 万还是 10 亿,固定只占 12KB 内存。虽然有 0.81% 的误差,但对于实时大盘展示完全够用。

3. 多维度 BI 分析 -> ClickHouse

  • 痛点:老板要看“北京地区、使用 iPhone、版本 v2.0 的日活”。

  • 解法:Redis 做不到多维交叉。这时候数据要清洗入库ClickHouseDoris,利用它们内置的bitmap函数进行 SQL 级的多维聚合分析。

面试标准答案模板:这样说,技术总监会觉得你是“自己人”

把上面的推导串起来,这就是可以直接输出的“专家级”回答:

“面试官您好,这道题不能直接拍脑袋选数据结构,需要结合数据基数、ID 特征和业务场景来分层设计。

  1. 在 C 端实时场景(如判断用户是否登录):

    我会排除 Set 方案,因为它有 6.4GB 的内存开销和 BigKey 风险。

    我会首选 Redis Bitmap。对于 2 亿用户,内存仅需 24MB。为了防止热点,我会按 UserID 取模进行 分片 处理。

  2. 针对特殊 ID 场景(如雪花 ID):

    如果 ID 极其稀疏,Redis Bitmap 会造成空间浪费。我会引入 Roaring Bitmap 算法,或者在 Redis 外部维护一套‘UserID -> 自增 ID’的映射表。

  3. 在 B 端分析场景(如多维统计):

    如果业务需要统计‘北京地区+安卓’的日活,Redis 很难胜任。我会建议将数据落入 ClickHouse,利用其内置的 Bitmap 类型进行多维交叉分析。

总结就是:实时查状态用 Redis 分片 Bitmap,多维分析用 ClickHouse,大盘估算用 HyperLogLog。”

写在最后

Redis 面试题从来不是考你“API 熟不熟”,而是考你“对资源的掌控力”

  • Set是逻辑上的集合。

  • Bitmap是物理上的极致。

  • Roaring BitmapClickHouse是架构上的宽深。

遇到海量数据,先拿出计算器算内存,这才是资深开发该有的本能。

https://mp.weixin.qq.com/s/jjIG8AkM3rN8YJHMKvnwqQ

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 10:26:08

AI应用架构师的独特视角:人机协作新范式流程设计最佳实践

AI应用架构师的独特视角:人机协作新范式流程设计最佳实践关键词:人机协作、AI应用架构、流程设计、角色定位、反馈循环、责任边界、持续优化 摘要:当AI从“工具”变成“协作伙伴”,我们需要重新思考人与AI的关系——不是“谁替代谁…

作者头像 李华
网站建设 2026/4/14 18:12:59

2025必备10个降AIGC工具,继续教育者必看!

2025必备10个降AIGC工具,继续教育者必看! AI降重工具:让学术写作更从容 随着人工智能技术的广泛应用,论文创作中出现的AIGC痕迹越来越成为学术界关注的焦点。对于继续教育领域的学习者和研究者而言,如何在保证内容质量…

作者头像 李华
网站建设 2026/4/11 7:20:17

PyTorch LRScheduler学习率调度器种类大全

PyTorch LRScheduler学习率调度器种类大全 在深度学习的训练过程中,一个看似微小却影响深远的超参数——学习率(Learning Rate),往往决定了模型能否高效收敛、是否陷入局部最优,甚至直接关系到最终性能的高低。过大&am…

作者头像 李华
网站建设 2026/4/15 11:22:19

Git Ignore忽略文件:排除PyTorch缓存和日志干扰

Git Ignore忽略文件:排除PyTorch缓存和日志干扰 在深度学习项目的日常开发中,你是否曾遇到这样的问题:一次简单的 git status 显示数十个新增文件,全是 .pth 模型权重、runs/ 日志目录或 .ipynb_checkpoints?当你准备…

作者头像 李华
网站建设 2026/4/9 17:47:46

Jupyter Notebook代码折叠:提升长脚本阅读体验

Jupyter Notebook代码折叠:提升长脚本阅读体验 在深度学习项目中,你是否曾面对一个长达上千行的 Jupyter Notebook 文件,翻来覆去却找不到训练循环的位置?当你试图向同事解释模型结构时,对方却被满屏的数据预处理代码淹…

作者头像 李华
网站建设 2026/4/13 8:40:26

YOLOv5 Anchor K-means聚类:自定义数据集锚框生成

YOLOv5 Anchor K-means聚类:自定义数据集锚框生成 在工业质检的产线上,一台视觉检测设备正高速扫描电路板——微小的焊点缺陷需要被精准识别。然而,使用标准YOLOv5模型训练时,小目标漏检严重,召回率始终难以突破80%。问…

作者头像 李华