news 2026/5/12 2:27:10

得物二面:Redis 中某个 Key 访问量特别大怎么办?我:Redis 能顶得住...

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
得物二面:Redis 中某个 Key 访问量特别大怎么办?我:Redis 能顶得住...

在线 Java 面试刷题(已更新239题,图文并茂):https://www.quanxiaoha.com/java-interview

面试考察点

  1. 基础掌握度:面试官不仅仅是想知道热点 Key 的定义,更是想知道你是否能区分热点 Key 和大 Key 的不同(一个是 "访问太多",一个是 "数据太大"),以及热点 Key 对 Redis 集群的具体影响。

  2. 排查能力:考察你是否知道生产环境中如何发现热点 Key(MONITORredis-cli --hotkeys、业务监控等),而不是等出了问题才去排查。

  3. 方案设计能力:能否针对不同场景给出对应的解决方案(本地缓存、读写分离、Key 分片),并说明各自的适用场景和优缺点。

核心答案

热点 Key 是指被大量客户端频繁访问的 Key,其 QPS 远高于其他 Key,导致单个 Redis 节点成为性能瓶颈。

维度

热点 Key

大 Key

问题本质

访问频率过高数据体积过大

核心危害

单节点 CPU / 网络被打满

主线程阻塞、网络拥塞

典型场景

秒杀商品、热门文章、热搜话题

一个 10MB 的 JSON、百万级集合

解决思路

分散访问压力

拆分数据体积

一句话结论:热点 Key 的核心问题是访问集中在一个节点上,解决方案是本地缓存(减少请求)+ 读写分离(分散读压力)+ Key 分片(分散到多个节点)

深度解析

一、热点 Key 到底有什么危害?

img

上图展示了热点 Key 在 Redis Cluster 中的危害:

  • 单节点过载:热点 Key 集中在某个节点上,该节点的 CPU、网卡带宽被瞬间打满,而其他节点可能很空闲。

  • 影响其他业务:同一节点上的其他 Key 也会因为资源被占满而响应变慢,产生 "邻居效应"。

  • 主从同步延迟:如果热点 Key 涉及写操作,主节点压力大时,主从复制延迟增大,读从节点可能拿到旧数据。

二、热点 Key 的典型场景

img

上图列出了热点 Key 的三种典型场景:

  • 突发热点:明星官宣、热搜话题、突发新闻等,短时间内大量用户访问同一页面,对应的 Redis Key 被疯狂读取。这类热点不可预测,最危险。

  • 预期内热点:秒杀商品、限时抢购等,在活动期间某些 Key 的 QPS 会飙到极高。这类热点可以提前准备

  • 架构设计不当:把全局配置、系统参数放在单个 Key 中,每个请求都要读取,造成人为的热点。

三、如何发现热点 Key?

方法一:redis-cli --hotkeys(Redis 4.0+)

# 需要先开启 maxmemory-policy 为 LFU 系列策略 redis-cli --hotkeys # 输出示例: # [Hot Key] user:profile:10086 (access count: 583210) # [Hot Key] seckill:goods:1001 (access count: 421305) # [Hot Key] hot:news:202 (access count: 389102)

关键点:

  • 基于 Redis 的 LFU 计数器统计,能直接列出访问频率最高的 Key。

  • 前提条件:必须将淘汰策略设为volatile-lfuallkeys-lfu,否则无法使用。

方法二:MONITOR命令(临时排查)

# 实时监控 Redis 执行的所有命令(危险!仅用于临时排查) redis-cli MONITOR | grep "GET\|HGET" | awk '{print $NF}' | sort | uniq -c | sort -nr | head -20 # 输出示例: # 583210 GET user:profile:10086 # 421305 GET seckill:goods:1001 # 389102 GET hot:news:202

关键点:

  • MONITOR会输出 Redis 执行的每一条命令,可以用管道统计哪些 Key 被访问最多。

  • 严重警告MONITOR本身会消耗 Redis 性能(高 QPS 下可能导致 10%~30% 性能下降),只能短时间使用,不能长期开启。

方法三:业务层面监控

/** * 简单的热点 Key 检测器 * 统计每个 Key 的访问频率,超过阈值告警 */ publicclass HotKeyDetector { // Key 访问计数器(可用 Guava Cache 设置滑动窗口) privatefinal Cache<String, AtomicLong> counterCache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.SECONDS) // 1 秒滑动窗口 .build(); // 热点阈值:1 秒内访问超过 1000 次 privatestaticfinallong HOT_THRESHOLD = 1000; public void recordAccess(String key) { AtomicLong counter = counterCache.get(key, () -> new AtomicLong(0)); long count = counter.incrementAndGet(); if (count == HOT_THRESHOLD) { // 触发告警 alertService.warn("检测到热点 Key:" + key + ",QPS:" + count); } } }

关键点:

  • 在应用层统计每个 Key 的访问频率,超过阈值触发告警。

  • 这种方式对 Redis 零侵入,不影响 Redis 性能,适合长期运行。

  • 可以结合 Sentinel、Prometheus 等监控系统做可视化展示。

四、热点 Key 的解决方案

img

上图展示了热点 Key 的四种解决方案:

  • 本地缓存(最优先):在应用服务器本地缓存一份热点数据,请求直接从本地内存返回,不经过 Redis,大幅降低 Redis 访问压力。

  • 读写分离:增加从节点,读请求分散到多个从节点,热点 Key 的读压力被多个节点分担,适合读多写少的场景。

  • Key 分片:将一个热点 Key 复制为 N 个副本,分布在不同节点上,读请求随机选择一个副本读取。

  • 限流 + 熔断:对热点 Key 的访问频率进行限流,超过阈值的请求直接返回降级数据,保护 Redis 和 DB 不被压垮。

五、方案详解与代码示例

方案一:本地缓存(Caffeine)
/** * 使用 Caffeine 本地缓存解决热点 Key * 适合:数据量小、更新不频繁、读多写少 */ publicclass LocalCacheSolution { // Caffeine 本地缓存 privatefinal Cache<String, String> localCache = Caffeine.newBuilder() .maximumSize(10000) // 最多缓存 1 万个 Key .expireAfterWrite(5, TimeUnit.SECONDS) // 5 秒过期(容忍短暂不一致) .recordStats() // 记录统计信息 .build(); public String getHotData(String key) { // 1. 先查本地缓存 String value = localCache.getIfPresent(key); if (value != null) { return value; // 本地缓存命中,直接返回,不访问 Redis } // 2. 本地缓存 miss,查 Redis value = redis.get(key); if (value != null) { localCache.put(key, value); // 回写本地缓存 return value; } // 3. Redis 也 miss,查 DB value = db.query(key); if (value != null) { redis.set(key, value, 30, TimeUnit.MINUTES); localCache.put(key, value); } return value; } }

关键点:

  • 使用 Caffeine 作为本地缓存(高性能、支持过期淘汰),5 秒过期容忍短暂的数据不一致。

  • 热点 Key 的请求大部分会命中本地缓存,Redis 的 QPS 可能从 30 万降到几千。

  • 注意:本地缓存适用于数据量小、更新不频繁的场景。如果数据更新频繁,要注意本地缓存和 Redis 的一致性问题。

方案二:Key 分片
/** * 热点 Key 分片方案 * 将一个热点 Key 复制为 N 个副本,分散到不同节点 */ publicclass HotKeyShardingSolution { privatestaticfinalint SHARD_COUNT = 16; // 分片数量 // 写入时:同时写入所有分片 public void setHotKey(String key, String value) { for (int i = 0; i < SHARD_COUNT; i++) { String shardKey = key + ":shard:" + i; redis.set(shardKey, value, 30, TimeUnit.MINUTES); } } // 读取时:随机选择一个分片读取 public String getHotKey(String key) { int shard = ThreadLocalRandom.current().nextInt(SHARD_COUNT); String shardKey = key + ":shard:" + shard; return redis.get(shardKey); } }

关键点:

  • 写入时同时写 N 个分片,读取时随机选一个分片,把 QPS 均摊到 N 个节点上。

  • 比如 30 万 QPS 的热点 Key,分 16 片后每个节点只承受约 1.9 万 QPS。

  • 代价:写入开销增大(写 N 次)、内存占用增大(存 N 份)、数据一致性维护成本高。

  • 适合读远多于写的场景(如秒杀商品详情)。

方案三:读写分离 + 热点探测(京东零售方案)
img

上图展示了京东零售的热点 Key 多级缓存方案:

  • 第一级:本地缓存(挡住 90% 请求):应用层统计 Key 访问频率,超过阈值自动标记为热点 Key,存入 Caffeine 本地缓存。

  • 第二级:Redis 读写分离(挡住 9% 请求):热点 Key 的读请求路由到从节点,分散读压力。

  • 第三级:DB 熔断兜底(1% 请求):Redis 全部 miss 时,查 DB 前先限流,DB 扛不住则返回降级数据。

  • 三级缓存协同工作,30 万 QPS 的热点 Key 也能稳定应对。

六、方案对比总结

方案

优点

缺点

适用场景

本地缓存

性能最好,直接挡在应用层

多实例数据不一致,内存有限

数据量小、更新不频繁

Key 分片

读写都能分散,通用性强

写入开销大,维护成本高

读远多于写

读写分离

对应用透明,运维层面解决

主从延迟,从节点成本

读多写少,有从节点资源

限流降级

兜底保命,实现简单

部分用户看到降级数据

兜底方案,配合其他方案使用

生产推荐组合:本地缓存(首选)+ 读写分离(分散读压力)+ 限流降级(兜底保命)。

面试高频追问

  1. 追问一:热点 Key 和大 Key 有什么区别?

    热点 Key 是访问频率过高,问题在于单节点 CPU / 网络被打满;大 Key 是数据体积过大,问题在于操作耗时长、阻塞主线程。两者可能同时存在(比如一个又大又被频繁访问的 Key),但解决思路完全不同:热点 Key 要分散访问,大 Key 要拆分数据。

  2. 追问二:本地缓存和 Redis 缓存的一致性怎么保证?

    本地缓存的过期时间设短一些(如 3~5 秒),容忍短暂的不一致。如果对一致性要求高,可以用Redis Pub/SubMQ 广播通知所有应用实例失效本地缓存。也可以接受最终一致性,大多数热点数据(商品详情、文章内容)短暂不一致是可接受的。

  3. 追问三:如何提前预知热点 Key?

    对于可预期的热点(如秒杀、大促),可以提前将热点数据加载到本地缓存中,活动开始前就预热好。对于突发热点,需要依赖热点探测机制实时发现并自动缓存。结合监控告警,当某个 Key 的 QPS 超过阈值时自动触发本地缓存。

常见面试变体

  • 变体一:"Redis 中某个 Key 访问量特别大怎么办?"

  • 变体二:"秒杀场景下 Redis 的热点 Key 如何处理?"

  • 变体三:"如何发现 Redis 中的热点 Key?"

  • 变体四:"本地缓存和 Redis 缓存怎么配合使用?"

记忆口诀

热点 Key:访问太多,单节点扛不住 —— "流量太集中"。

解决方案优先级:本地缓存(挡最多)> Key 分片(分散节点)> 读写分离(分散读)> 限流降级(兜底)。

与大 Key 区别:热点是 "来的人太多",大 Key 是 "东西太大搬不动"。

生产最佳实践:热点探测 + 本地缓存 + 读写分离 + 限流降级,四板斧组合使用。

总结

Redis 热点 Key 是指被大量客户端频繁访问的 Key,会导致单个节点 CPU 和网络被打满。发现热点 Key 可以用--hotkeysMONITOR、业务层监控等手段。解决方案的核心是分散访问压力:优先使用本地缓存(Caffeine)挡住大部分请求,配合 Key 分片或读写分离分散 Redis 的读压力,最后用限流降级兜底保命。

加入小哈的星球,你将获得:专属的项目实战(多个项目) / 1v1 提问 /Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论

  • 《秒杀系统设计》正在更新中..., 由单体到微服务,渐进式地搭建一个支撑高并发的秒杀系统。

  • 《从零手撸:Spring AI 应用项目》已完结, 基于 Spring AI + Spring Boot 3.x + JDK 21;

  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/

  • 《从零手撸:前后端分离博客项目(全栈开发)》2期已完结,演示链接:http://116.62.199.48/;

  • 专栏阅读地址:https://www.quanxiaoha.com/column

截止目前,累计输出 120w+ 字,讲解图 4013+ 张,还在持续爆肝中..戳我加入学习,解锁全部项目,已有4500+小伙伴加入

1. 我的私密学习小圈子,从0到1手撸企业实战项目~ 2. 面试官:ZSet 的底层实现是什么?(修订版) 3. 百度面试官:Redis 内存满了怎么办?你有想过吗? 4. 滴滴二面:你项目为什么选择 RocketMQ,而不是 Kafka? 我:支支吾吾....
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀,谢谢啦
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 14:07:07

3分钟极速汉化Axure:免费中文语言包全版本支持指南

3分钟极速汉化Axure&#xff1a;免费中文语言包全版本支持指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 你是否还在为Axur…

作者头像 李华
网站建设 2026/4/19 9:48:29

Kube-Vip ARP模式详解:简单高效的控制平面高可用方案

Kube-Vip ARP模式详解&#xff1a;简单高效的控制平面高可用方案 【免费下载链接】kube-vip Kubernetes Control Plane Virtual IP and Load-Balancer 项目地址: https://gitcode.com/gh_mirrors/ku/kube-vip Kube-Vip ARP模式是Kubernetes控制平面高可用的终极解决方案…

作者头像 李华
网站建设 2026/4/18 3:32:00

AlertKit核心组件详解:深入解析Done、Heart、Error等图标动画

AlertKit核心组件详解&#xff1a;深入解析Done、Heart、Error等图标动画 【免费下载链接】AlertKit Native alert from Apple Music & Feedback. Contains Done, Heart & Message and other presets. 项目地址: https://gitcode.com/gh_mirrors/al/AlertKit Al…

作者头像 李华
网站建设 2026/5/11 1:46:43

阿里小云KWS模型部署避坑指南:Ubuntu20.04环境配置详解

阿里小云KWS模型部署避坑指南&#xff1a;Ubuntu20.04环境配置详解 1. 引言 语音唤醒技术正在改变我们与设备交互的方式&#xff0c;阿里小云KWS&#xff08;关键词检测&#xff09;模型作为一款轻量级语音唤醒引擎&#xff0c;为嵌入式场景和智能设备提供了高效的解决方案。…

作者头像 李华