Redis 热 Key 治理实战:发现访问倾斜、拆分缓存和本地兜底
接口压测时最容易被忽略的问题之一,是缓存并没有慢,但某一个 Key 被打得太热:大部分请求都挤到同一个 Redis 节点,应用线程在等待缓存返回,数据库又担心缓存失效后的瞬时回源。热 Key 治理不是简单加机器,而是先找到倾斜,再让请求有层次地被削峰。
适合人群:正在维护 Redis 缓存、商品详情、配置中心、活动页、排行榜等高频读取接口的后端同学。读完后你可以把热 Key 排查步骤和保护链路直接套到自己的业务里。
目录
- 热 Key 的典型现象
- 如何定位访问倾斜
- 保护链路:本地短缓存 + singleflight + 过期时间抖动
- 拆分缓存与降级策略
- 常见坑和上线检查
一、热 Key 的典型现象
热 Key 指某个或少数几个缓存 Key 承担了远高于平均值的访问量。它常见于秒杀商品详情、首页配置、热门文章、城市列表、直播间状态等场景。问题出现时,Redis 整体 QPS 可能看起来还好,但某个分片的网络、CPU 或连接队列已经明显偏高。
可以先用三类信号判断是否有访问倾斜:
- 应用侧:某个接口 P95/P99 抖动,慢日志集中在读取同一类缓存。
- Redis 侧:某个节点的输入输出流量明显高于其他节点。
- 业务侧:某个商品、活动、配置在短时间内被大量读取。
二、如何定位访问倾斜
定位热 Key 时,先从低侵入的指标和采样开始。线上不要直接全量扫描大库,优先用 Redis 自带统计、代理层访问日志、应用埋点组合判断。
# 观察命令调用量和耗时趋势 redis-cli info commandstats | grep -E 'cmdstat_get|cmdstat_mget|cmdstat_hget' # 在支持 LFU 的实例上观察热点采样 redis-cli --hotkeys # 观察延迟变化,确认是否和业务高峰同步 redis-cli --latency-history -i 1
如果应用侧可以加一层轻量采样,建议记录“缓存 Key 模板 + 业务 id + 命中状态 + 耗时”。不要只记录完整 Key,否则日志量会上去;也不要只记录接口名,否则无法定位到具体对象。

三、保护链路:本地短缓存 + singleflight + 过期时间抖动
发现热 Key 后,最实用的一条保护链路是:应用先查本地短缓存,本地没有再查 Redis;如果 Redis 也没有,用 singleflight 合并同一 Key 的加载请求;写回缓存时给 TTL 加一点随机抖动,避免一批热点同时失效。
type HotCache struct {
redis RedisClient
local LocalCache
group singleflight.Group
}
func (h *HotCache) GetProduct(ctx context.Context, id int64) ([]byte, error) {
key := fmt.Sprintf("product:%d", id)
if value, ok := h.local.Get(key); ok {
return value, nil
}
value, err, _ := h.group.Do(key, func() (any, error) {
if cached, ok := h.local.Get(key); ok {
return cached, nil
}
data, err := h.redis.Get(ctx, key)
if err == nil && len(data) > 0 {
h.local.Set(key, data, 3*time.Second)
return data, nil
}
fresh, err := loadProductFromDB(ctx, id)
if err != nil {
return nil, err
}
ttl := 5*time.Minute + time.Duration(rand.Intn(60))*time.Second
_ = h.redis.Set(ctx, key, fresh, ttl)
h.local.Set(key, fresh, 3*time.Second)
return fresh, nil
})
if err != nil {
return nil, err
}
return value.([]byte), nil
}
这段逻辑的重点不是把本地缓存时间设得很长,而是用 2 到 5 秒挡住瞬时尖峰。singleflight 负责把同一 Key 的并发加载合成一次,TTL 抖动则减少同一批缓存同时过期的概率。

四、拆分缓存与降级策略
如果一个 Key 长期保持极高访问量,单纯靠本地缓存还不够,可以考虑按业务读法拆分:
- 把大对象拆成基础信息、库存状态、活动状态等多个 Key,减少每次读取的数据量。
- 对只读配置类数据增加本地定时刷新,让接口请求少走远程缓存。
- 对排行榜、热门列表这类读多写少数据,准备只读副本或静态快照。
- 对非核心字段设置降级默认值,缓存异常时优先保住主流程。
拆分时要注意一致性边界。比如商品标题和封面可以慢一点刷新,价格和库存不能随意放宽。不同字段的刷新频率不同,缓存模型也应该不同。
五、常见坑和上线检查
1. 本地缓存不是越久越好
本地缓存时间过长会带来数据不一致,尤其是价格、权限、状态类字段。热 Key 保护通常只需要几秒,让峰值请求在应用内被吸收即可。
2. 只加随机 TTL 不等于解决热 Key
TTL 抖动主要解决“同时失效”,但访问倾斜仍然存在。真正的治理要配合本地短缓存、合并加载、拆分对象和限流降级。
3. 上线前要看三组指标
- 接口 P95/P99 是否下降,错误率是否稳定。
- Redis 热点节点的流量是否回落,连接数是否平稳。
- 数据库回源次数是否可控,缓存失效时是否出现突刺。
总结
Redis 热 Key 治理的顺序可以记成四步:先用指标和采样发现倾斜,再用本地短缓存削峰,用 singleflight 合并加载,用 TTL 抖动和缓存拆分降低集中失效风险。这样做的好处是改动小、回滚简单,也能把压力从 Redis 单点分散到应用层的短时缓冲里。
Python pathlib 批量整理文件实战:按扩展名归档和冲突重命名
- 上一篇
- Python pathlib 批量整理文件实战:按扩展名归档和冲突重命名
- 下一篇
- Go HTTP 服务优雅停机实战:信号处理、摘流和超时关闭
-
- 数据库 · Redis | 2天前 | Redis ·
- Redis Sentinel故障转移期间客户端重连的配置方法
- 108浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · cluster ·
- Redis Cluster跨槽批量读取的拆分方案
- 461浏览 收藏
-
- 数据库 · Redis | 2天前 | eval Redis Lua脚本 Redis库存扣减 Redis原子操作 请求幂等
- Redis Lua脚本保证库存扣减与记录写入原子性的设计
- 226浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis Hash与JSON字符串存储对象的选择边界
- 476浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis ZSET延迟队列 Redis有序集合 Redis重复任务 ZADD NX 延迟任务重试
- Redis ZSET实现延迟队列并控制重复任务的做法
- 489浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis XAUTOCLAIM批量接管失联消费者消息的实现方法
- 485浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · 消息队列 · redis streams XREADGROUP XACK
- Redis Stream用消费组实现可重试任务队列的方案
- 349浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis ·
- Redis Sentinel读取主从切换后的服务发现结果的实现方法
- 236浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · BitMap · BITFIELD Redis Bitmap Redis bitmap偏移 SETBIT GETBIT
- Redis bitmap计算位图偏移并避免越界的实现方法
- 130浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis HyperLogLog用近似结构估算去重计数的实现方法
- 364浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis Pub/Sub重连后恢复订阅关系的实现方法
- 309浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 184次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 240次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 194次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 175次使用
-
- CMMLU
- 深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
- 166次使用
-
- 接口返回的数据和数据库不一致怎么办?按数据生命周期排查
- 2026-06-27 398浏览
-
- Go与Redis实现分布式互斥锁和红锁
- 2022-12-22 117浏览
-
- Go+Redis实现延迟队列实操
- 2023-02-23 426浏览
-
- 关于golangtest缓存问题
- 2023-01-01 298浏览
-
- 一文搞懂Go语言操作Redis的方法
- 2023-01-07 171浏览

