适用版本:Redis 7.2.x
Redis 在线上通常承担的是高频访问、低延迟响应的核心职责,因此一旦它出现异常,往往不是“某个接口慢一点”这么简单,而是会引发连锁反应:接口超时、数据库回源暴涨、线程堆积、整体 RT 上升,严重时甚至引发级联故障。
很多团队在学习 Redis 时,重点放在数据结构和命令用法上,但到了生产环境,真正考验能力的往往是:怎么判断问题在哪、怎么快速止血、怎么避免重复事故。
这篇文章从工程实践出发,整理一套 Redis 生产问题排查思路,覆盖典型现象、常见根因、分析方法和风险控制。
一、排查 Redis 问题,先看清是“Redis 自己有问题”还是“业务使用方式有问题”
线上很多“Redis 问题”并不一定是 Redis 服务故障,常见可以分成两类:
1. Redis 自身层面的问题
- CPU 飙高;
- 内存不足或淘汰异常;
- 慢查询;
- 持久化阻塞;
- 网络抖动;
- 主从复制延迟;
- 集群槽位迁移期间抖动。
2. 业务使用层面的问题
- 热点 key 访问过于集中;
- key 设计不合理,导致大 value 或超高基数;
- 大量 key 同时过期;
- 缓存穿透回源数据库;
- pipeline / 批量操作使用不当;
- 序列化对象过大;
- 锁使用不规范导致竞争放大。
所以排查第一步不要急着下结论,而是先回答:
- Redis 本身资源是否异常?
- 请求模式是否突然变化?
- 是少量热点 key 的问题,还是整体性能问题?
- 数据库/应用指标是否同步恶化?
二、一个通用的生产排查顺序
建议按下面顺序排查,效率通常最高。
第一步:确认业务现象
先看用户和上游实际感知到什么:
- 接口变慢?
- 错误率升高?
- 某个功能不可用?
- 只有单个接口异常,还是全站异常?
第二步:看监控总览
重点看:
- Redis QPS;
- 命中率;
- 平均延迟、P99 延迟;
- CPU、内存;
- 网络流量;
- 主从复制延迟;
- 连接数、阻塞客户端数;
- evicted_keys、expired_keys;
- slowlog 数量。
第三步:结合应用侧指标
要同步看:
- 应用线程池是否堆积;
- 数据库 QPS 是否上升;
- 下游接口是否同步超时;
- 某次发布、扩容、活动切流是否刚发生。
第四步:收敛到具体问题类型
通常最终会落到以下几类:
- 热点 key;
- 大 key / 大 value;
- 集中过期;
- 慢命令;
- 内存淘汰;
- 网络连接异常;
- 复制或集群切换问题。
三、问题一:Redis 延迟突然升高
1. 现象
- 应用访问 Redis 的 RT 从 1ms 上升到几十毫秒甚至几百毫秒;
- 接口整体 RT 同步恶化;
- 但 Redis 进程可能并没有彻底不可用。
2. 典型根因
根因一:慢命令
比如:
- 对超大集合执行全量遍历;
- 使用
KEYS *; - 大量
SMEMBERS、HGETALL、LRANGE 0 -1; - Lua 脚本处理数据量过大。
根因二:大 key 读取
某些 key 的 value 非常大,读取与序列化成本高,导致单次命令耗时异常。
根因三:CPU 打满
例如热点 key、复杂 Lua、频繁过期淘汰、RDB/AOF 压力等都可能推高 CPU。
根因四:网络抖动
Redis 本身没问题,但客户端到 Redis 的网络延迟上升,也会表现为 Redis RT 变高。
3. 处理思路
- 先看 slowlog 是否有明显慢命令;
- 定位是否某类命令占比突然上升;
- 检查大 key、大 value;
- 对照 CPU、网络、连接数变化;
- 排查是否有新发布引入异常访问模式。
4. 风险与止血
- 立即下线或限制危险命令;
- 对热点接口做限流;
- 对大 key 做拆分或延迟治理;
- 必要时临时降级部分缓存依赖。
四、问题二:缓存命中率突然下降,数据库被打高
这是最常见的线上联动故障之一。
1. 典型现象
- Redis 命中率下降;
- 数据库 QPS 飙升;
- 应用线程数上升;
- 接口开始超时。
2. 常见原因
原因一:大量 key 同时过期
比如统一设置 30 分钟 TTL,结果某批数据在同一时间段集中失效。
原因二:热点 key 被击穿
单个超热点 key 过期,海量请求回源数据库。
原因三:误删缓存
某次发布或脚本操作误删了业务前缀 key。
原因四:Redis 节点异常
客户端读不到缓存,只能全部回源。
3. 排查点
expired_keys是否短时间激增;- 是否存在某个热点接口或 key 访问激增;
- 最近是否有批量预热/批量失效操作;
- 应用日志里是否出现大量缓存 miss;
- 数据库中是否出现同一类查询骤增。
4. 处理方案
- 对数据库立即限流保护;
- 热点 key 立刻手工预热;
- 对核心接口降级返回旧值或静态兜底;
- 补上随机 TTL、互斥重建、空值缓存等基础治理。
五、问题三:内存持续上涨,最终触发淘汰或 OOM
1. 现象
- used_memory 持续增长;
- evicted_keys 开始增加;
- 命中率下降;
- 某些 key 刚写入就被淘汰;
- 严重时写入失败或实例抖动。
2. 常见原因
原因一:业务写入量增加,但 TTL 过长甚至无过期
缓存原本是临时数据,但如果大量 key 没有 TTL,很容易越积越多。
原因二:空值缓存或短期数据没有及时清理
虽然单个 key 很小,但数量巨大时也会占用可观内存。
原因三:大 key
少量超大 Hash / Set / String 就可能吞掉大量内存。
原因四:淘汰策略与业务模型不匹配
例如业务依赖 LRU,但实例配置成不淘汰或随机淘汰,可能造成命中率异常。
3. 排查方法
- 看 key 数量和平均 value 大小;
- 分析大 key;
- 看是否存在无 TTL key 激增;
- 对照业务发布、活动、导数任务;
- 检查淘汰策略是否合理。
4. 风险与处理
- 直接扩容只能缓解,不解决根因;
- 大 key 删除不能粗暴一次性执行,可能阻塞;
- 应优先处理无 TTL 冗余数据和明显异常写入。
5. 实践建议
- 缓存数据默认都应有 TTL;
- 定期巡检无 TTL key;
- 对大 key 做告警阈值;
- 重要业务做容量评估,不要靠事故倒逼治理。
六、问题四:热点 key 导致单点瓶颈
1. 现象
- Redis 总体 QPS 不算高,但某个分片或某个实例压力很高;
- 某个接口 RT 不稳定;
- CPU 不是持续高,而是伴随某类请求波峰抖动。
2. 根因
一个或少数几个 key 被超高频访问,例如:
- 热门商品详情;
- 全站配置;
- 某个排行榜;
- 大促会场基础信息。
3. 解决思路
方案一:本地缓存分流
对极热点数据加 Caffeine 等本地缓存,减少 Redis 压力。
方案二:热点 key 永不过期 + 主动更新
避免在流量高峰时自然失效。
方案三:逻辑过期
先返回旧值,再异步刷新,避免集中回源。
方案四:拆分热点
如果一个 key 中包含过多维度信息,考虑拆分读取路径,降低单点访问集中度。
4. 风险提示
- 本地缓存引入多节点一致性问题;
- 热点 key 永不过期必须有主动治理链路;
- 热点识别需要依赖监控,不能靠人工猜测。
七、问题五:大 key 引发阻塞与抖动
1. 什么是大 key
没有绝对统一标准,但通常指:
- 单个 String 值特别大;
- 单个 Hash 字段数过多;
- Set / ZSet / List 元素数量异常大;
- 单次读取、删除、迁移成本明显偏高。
2. 为什么大 key 危险
- 读取慢;
- 删除慢;
- 网络传输开销大;
- 主从复制压力大;
- 集群迁移成本高。
3. 常见触发场景
- 把整页聚合数据直接缓存成一个巨大 JSON;
- 把用户所有行为历史都塞进一个 List;
- 使用 Hash 缓存全量维度,字段持续膨胀;
- 排行榜没有做历史滚动归档。
4. 治理方案
- 拆 key,按业务维度分桶;
- 控制单 key 数据上限;
- 大集合采用分页或分片设计;
- 删除时使用异步 unlink 或分批清理策略。
5. 经验判断
如果一个 key 的存在已经影响:
- 读取 RT;
- 删除耗时;
- 复制或迁移效率;
那它大概率就已经是工程问题,而不是“暂时还能用”。
八、问题六:连接数暴涨或客户端阻塞
1. 现象
- connected_clients 持续升高;
- blocked_clients 上升;
- 应用侧报连接超时、读写超时;
- 部分实例 CPU 不高,但请求已经开始堆积。
2. 常见原因
- 连接池配置过小或泄漏;
- 慢查询导致连接占用时间拉长;
- pipeline 使用不当,请求堆积;
- 短连接模式频繁创建连接;
- 网络异常导致大量连接重试。
3. 排查建议
- 看应用连接池使用率;
- 看 Redis 慢命令与连接数变化是否同步;
- 看客户端超时配置是否合理;
- 检查最近是否做过 SDK 升级或连接池改造。
4. 处理思路
- 优先解决慢命令;
- 调整连接池与超时参数;
- 避免无意义短连接;
- 对重试做限速,防止雪上加霜。
九、问题七:主从复制延迟或切换后出现读写异常
1. 典型现象
- 写入后立刻读不到;
- 从库读延迟明显;
- 主从切换后短时间报错增多;
- 分布式锁、缓存更新等逻辑出现偶发异常。
2. 常见原因
- 主节点写压力太大;
- 网络抖动导致复制延迟;
- 大 key / 大批量写入拖慢复制;
- 故障切换期间客户端重连不及时。
3. 风险点
- 读写分离场景下更容易暴露一致性问题;
- 使用 Redis 锁时,主从切换可能破坏锁语义;
- 切换期间如果客户端没有良好重试策略,容易出现雪崩式失败。
4. 处理建议
- 关键数据尽量避免依赖从库立即可见;
- 控制大 key 和突发大写入;
- 客户端要有连接重建与错误分类机制;
- 对锁、幂等等关键逻辑认清 Redis 的一致性边界。
十、问题八:Lua 脚本或事务导致执行时间异常
1. 场景
Redis 单线程执行命令,如果 Lua 脚本处理逻辑太重,就会阻塞其他请求。
2. 常见误区
- 以为脚本原子执行就可以放很多业务逻辑;
- 在 Lua 中遍历大集合;
- 用脚本做复杂聚合计算。
3. 排查方法
- 看 slowlog 是否出现脚本相关命令;
- 对照发布记录,看是否新上线脚本逻辑;
- 检查脚本是否操作了大 key。
4. 治理建议
- Lua 只做小而确定的原子逻辑;
- 避免在脚本里处理大数据集;
- 对脚本执行耗时建立监控。
十一、生产止血优先级:先保系统,再做根因修复
线上事故中,先后顺序非常重要。
第一优先级:止血
- 限流;
- 降级;
- 手工预热热点缓存;
- 暂停危险任务或批处理;
- 必要时切走部分流量。
第二优先级:收敛范围
- 是全局问题还是局部业务问题;
- 是 Redis 整体抖动还是个别 key 异常;
- 是服务端问题还是客户端问题。
第三优先级:根因定位
- 结合 slowlog、监控曲线、发布记录、业务日志;
- 不只看单点指标,要看链路联动。
第四优先级:补治理能力
- TTL 随机化;
- 热点识别;
- 大 key 巡检;
- 空值缓存;
- 限流熔断;
- 监控告警完善。
十二、建议长期建设的监控清单
如果想让 Redis 问题更早暴露,建议长期建设下面这些指标与告警:
基础资源指标
- CPU;
- 内存;
- 网络吞吐;
- 连接数;
- blocked_clients。
性能指标
- QPS;
- 平均 RT、P95、P99;
- slowlog 次数;
- 每类命令调用占比。
缓存治理指标
- 命中率;
- expired_keys;
- evicted_keys;
- 热点 key TOP;
- 大 key TOP。
业务联动指标
- 数据库回源 QPS;
- 应用线程池堆积;
- 接口超时率;
- 降级命中次数。
十三、一套简化的排查口诀
如果要把 Redis 线上排查压缩成一套方便记忆的方法,可以记成:
1. 先看现象
慢了?错了?打满了?还是读不到了?
2. 再看全局指标
QPS、命中率、RT、CPU、内存、连接数、slowlog。
3. 再看是否联动到下游
数据库有没有被打高?应用线程有没有堆积?
4. 最后看具体问题模型
- 慢命令;
- 热点 key;
- 大 key;
- 集中过期;
- 内存淘汰;
- 网络抖动;
- 主从复制问题。
这套顺序能避免一上来就陷入细节,也能降低误判概率。
十四、小结
Redis 生产问题排查,难点不只是会不会看命令,而是能不能快速把问题归类,并判断优先级。工程实践里,真正高效的处理方式通常是:
- 先判断影响面:是局部异常还是全局故障;
- 先止血再根因:限流、降级、预热,优先保住主链路;
- 结合链路看问题:Redis 指标必须和应用、数据库一起看;
- 把问题模型化:热点、大 key、雪崩、慢命令、复制延迟,各有各的解法;
- 把治理前置:监控、TTL 策略、容量规划、热点治理,比事故后的补救更重要。
Redis 快,但不是“天然不会出问题”。线上稳定性的关键,往往不在于会多少命令,而在于:能不能在问题刚露头时就识别出来,并用工程手段把影响范围控制住。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!