返回首页

Redis 工程实践6.4:生产常见问题排查

适用版本: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 *
  • 大量 SMEMBERSHGETALLLRANGE 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 快,但不是“天然不会出问题”。线上稳定性的关键,往往不在于会多少命令,而在于:能不能在问题刚露头时就识别出来,并用工程手段把影响范围控制住。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

Redis 工程实践6.3:缓存一致性与雪崩、击穿、穿透

下一篇

Nginx 入门:1 Nginx 简介与安装