• 2026年7月16日
  • 5 分钟阅读
  • SystemDo

Redis 缓存服务常见故障怎么排查?问题定位与维护清单

本文从系统部署维护视角梳理 Redis 缓存服务常见故障类型、排查步骤、证据保留方法及长期治理策略,帮助开发与运维团队建立可复用的故障响应流程。

Redis 缓存服务常见故障怎么排查?问题定位与维护清单
SystemDo
SystemDo

软件定制开发团队

"真正有价值的技术内容,应该能帮助客户更快判断方向、预算和落地路径。"

故障排查前的准备:建立基线

排查任何 Redis 故障之前,必须知道“正常是什么样子”。没有基线就谈不上异常。

基线数据至少包含以下三项:

  • 正常业务高峰期的 QPS(每秒查询数)与平均响应时间。例如,某用户管理系统在白天峰值的 QPS 为 5000,平均响应时间 1.2 ms。
  • 内存使用率与 key 数量。记录 used_memory_human、total_connections_received、keyspace_hits/keyspace_misses 的日变化曲线。
  • 网络往返时延。从应用服务器到 Redis 服务器的 ping 延迟,建议保留 7 天以上的历史数据。

如果 Redis 实例运行在云托管服务(如阿里云、腾讯云、AWS ElastiCache),还需记录连接数限制、最大内存策略(maxmemory-policy)等配置快照。

没有基线时,排查只能依赖经验猜测,效率低下且容易误判。

故障类型一:连接超时与连接数耗尽

症状

应用日志中出现“connection timeout”“max number of clients reached”“Cannot connect to Redis”等错误。监控面板显示连接数达到上限(默认 10000,可通过 maxclients 配置修改)。

排查顺序

1. 检查当前连接数:`INFO clients` 输出中的 connected_clients 字段。
2. 对比 maxclients 配置:`CONFIG GET maxclients`。如果 connected_clients 已接近或等于 maxclients,说明连接池耗尽。
3. 检查是否存在连接泄漏:查看应用端的连接池配置,确认是否在每次操作后归还连接。常见错误是使用了短连接或未正确关闭连接池。
4. 检查是否遭受恶意攻击或爬虫:通过 `CLIENT LIST` 查看所有连接来源 IP,如果某个 IP 的连接数异常高,考虑防火墙限流。

原因与条件

连接数耗尽通常发生在以下条件下:

  • 应用端连接池大小设置过大且业务并发突增。例如,某电商秒杀活动期间,连接池大小从 50 临时调至 500,但 Redis 实例的 maxclients 未同步调整。
  • 应用端未设置连接超时或超时过长。连接建立后长期闲置不归还,导致连接池被占满。
  • 网络不稳定导致连接被 TCP 层面保留(TIME_WAIT 状态),但应用端认为连接已断开并不断创建新连接。

快速恢复

临时增加 maxclients(例如 `CONFIG SET maxclients 20000`),同时重启应用端连接池。但注意:maxclients 不能超过操作系统允许的最大文件句柄数(`ulimit -n`)。永久修复需要调整应用端连接池策略并增加监控告警。

故障类型二:慢查询与响应延迟飙升

症状

业务响应时间从 1-2 ms 突然上升到 50-200 ms,甚至超时。Redis 监控面板显示延迟曲线陡增。

排查顺序

1. 启用慢查询日志:设置 `SLOWLOG GET 100` 查看最近 100 条慢查询。默认慢查询阈值是 10 ms(可通过 slowlog-log-slower-than 调整)。
2. 分析慢查询命令类型:常见慢命令包括 KEYS、SMEMBERS、HGETALL、ZRANGE(未加 LIMIT)、大量数据的 SORT 等。KEYS 命令在百万级 key 规模下会导致 Redis 阻塞数秒。
3. 检查是否存在大 key:使用 `MEMORY USAGE key` 或 `DEBUG OBJECT key` 估算单个 key 的内存占用。大 key 通常指单个 key 占用超过 10 MB 或包含超过 1 万个元素。大 key 的删除操作(DEL)也会阻塞主线程。
4. 检查是否触发了持久化操作:如果启用 AOF 持久化且设置 `appendfsync always`,每次写入都会同步磁盘,性能会显著下降。`appendfsync everysec` 是多数生产环境的推荐值。
5. 检查网络带宽:使用 `INFO STATS` 观察 instantaneous_input_kbps 和 instantaneous_output_kbps,如果接近网络接口上限,延迟也会上升。

原因与条件

慢查询的核心原因是 Redis 是单线程处理命令。任何耗时超过几毫秒的命令都会阻塞后续所有请求。大 key 的读写、全量扫描命令、频繁的持久化同步是主要诱因。

治理建议

  • 用 SCAN 替代 KEYS,用 SSCAN/HSCAN/ZSCAN 替代 SMEMBERS/HGETALL/ZRANGE(不设 LIMIT)。
  • 对大 key 进行拆分或设置过期时间,避免单个 key 体量过大。
  • 将慢查询阈值调整为 1 ms(`SLOWLOG GET 100` 配合 `SLOWLOG RESET`),提前发现潜在慢操作。

故障类型三:内存溢出与淘汰策略失效

症状

Redis 日志中出现“OOM command not allowed when used memory > 'maxmemory'”错误。或者,业务发现部分缓存数据突然消失,命中率骤降。

排查顺序

1. 检查当前内存使用:`INFO MEMORY` 中的 used_memory_human 和 maxmemory_human。
2. 确认淘汰策略:`CONFIG GET maxmemory-policy`。默认策略是 noeviction,即内存写满后拒绝写入。其他策略包括 allkeys-lru、allkeys-lfu、volatile-lru、volatile-ttl 等。
3. 分析内存占用分布:使用 `MEMORY STATS` 或第三方工具(如 redis-rdb-tools)分析 RDB 文件,找出占用内存最多的 key 类型和 key 前缀。
4. 检查是否有未设置过期时间的 key 持续增长。如果策略是 volatile-lru,只有设置了过期时间的 key 才会被淘汰,未设过期时间的 key 会永久占用内存。

原因与条件

内存溢出通常发生在以下场景:

  • 业务数据量增长超出预期,且 maxmemory 配置未及时调整。
  • 淘汰策略选择不当。例如,业务希望淘汰最久未访问的数据,但使用了 volatile-lru,而大量 key 未设过期时间,导致淘汰机制失效。
  • 存在内存泄漏:虽然 Redis 自身内存管理稳定,但某些第三方模块(如 RedisGraph、RedisTimeSeries)或 Lua 脚本中未释放的资源可能导致内存异常增长。

治理建议

  • 根据业务访问模式选择淘汰策略。通用推荐:allkeys-lru 适用于纯缓存场景;volatile-ttl 适用于需要精确控制过期时间的场景。
  • 为所有缓存 key 设置合理的过期时间,避免无限制增长。
  • 定期使用 `MEMORY PURGE`(Redis 4.0+)手动触发内存碎片回收。

故障类型四:主从延迟与数据不一致

症状

读操作从从库获取到过期数据或与主库数据不一致。监控显示从库的 repl_backlog_histlen 持续增长,或 master_repl_offset 与 slave_repl_offset 差距过大。

排查顺序

1. 检查主从复制状态:`INFO REPLICATION` 中的 master_link_status、slave_lag(单位秒)、master_repl_offset 和 slave_repl_offset。
2. 确认从库是否处于同步中:如果 master_link_status 为 down,说明复制链路断开。常见原因包括网络抖动、主库内存不足触发 OOM killer、主库重启。
3. 检查复制积压缓冲区大小:`CONFIG GET repl-backlog-size`。默认 1 MB,如果主库写入量较大且从库延迟时间较长,积压缓冲区可能被覆盖,导致从库需要全量重同步。
4. 检查从库是否启用了读写分离且读取过期数据:Redis 默认不会主动删除过期 key,而是在访问时惰性删除。从库可能返回已过期但尚未被删除的数据。需要确认业务是否依赖从库读取实时数据。

原因与条件

主从延迟在以下条件下更容易发生:

  • 主库写入量极大,从库单线程无法跟上写入速度。
  • 主库与从库之间的网络延迟较高(例如跨机房部署)。
  • 从库同时处理大量客户端读请求,消耗了 CPU 资源。

治理建议

  • 对延迟敏感的读操作强制路由到主库。
  • 增大 repl-backlog-size(建议设为主库每秒写入量的 30 倍),减少全量重同步概率。
  • 使用 Redis Sentinel 或 Redis Cluster 的自动故障转移,避免长时间人工干预。

故障类型五:持久化失败与数据丢失

症状

Redis 重启后部分数据丢失,或 AOF 文件损坏导致无法启动。

排查顺序

1. 检查持久化配置:`CONFIG GET save`(RDB 触发条件)、`CONFIG GET appendonly`(是否开启 AOF)、`CONFIG GET appendfsync`(AOF 同步策略)。
2. 查看日志:检查 Redis 日志中是否有“Can't save in background: fork: Cannot allocate memory”或“AOF: rewrite failed”等错误。
3. 检查磁盘空间:`INFO PERSISTENCE` 中的 rdb_last_bgsave_status 和 aof_last_rewrite_status。如果磁盘空间不足,RDB 或 AOF 写入会失败。
4. 检查系统内存:RDB 持久化时 Redis 会 fork 子进程,如果系统内存不足,fork 可能失败。建议预留至少 1-2 GB 空闲内存,或启用 overcommit_memory(`sysctl vm.overcommit_memory=1`)。

原因与条件

数据丢失通常发生在以下情况:

  • 仅使用 RDB 持久化,且两次快照之间 Redis 崩溃。RDB 默认每 5 分钟快照一次,崩溃时可能丢失 5 分钟的数据。
  • AOF 文件被截断或损坏。在系统突然断电或磁盘故障时,AOF 文件可能不完整。
  • 持久化配置错误:例如 appendonly 设为 no,或 save 配置为空。

治理建议

  • 生产环境建议同时开启 RDB 和 AOF。RDB 用于快速恢复,AOF 提供更细粒度的数据保护。
  • 设置 appendfsync everysec 平衡性能与安全。
  • 定期检查持久化状态,并监控磁盘空间和系统内存。

证据保留:排查前的关键步骤

故障发生时,不要急于重启或恢复。先保留以下证据,否则可能丢失定位线索:

  • 当前 Redis 运行状态快照:执行 `INFO ALL` 并保存输出。如果 Redis 已无法响应,尝试通过 `redis-cli -h host -p port --raw info all` 获取。
  • 慢查询日志:`SLOWLOG GET 100` 保存到文件。
  • 客户端连接列表:`CLIENT LIST` 保存。
  • 系统资源状态:`top`、`free -m`、`df -h`、`netstat -anp | grep 6379` 的输出。
  • 应用日志:收集故障前后 15 分钟的应用端日志,重点关注连接异常、超时、重试日志。
  • 监控数据:从 Prometheus、Grafana、Zabbix 等监控系统中导出 CPU、内存、网络、连接数的时间序列图。

保留证据后,再执行重启或切换操作。

维护清单:从被动救火到主动治理

基于上述故障类型,整理一份可定期执行的维护清单,降低故障发生概率。

每日检查

  • 检查 Redis 进程是否存活:`systemctl status redis` 或进程监控。
  • 检查内存使用率:超过 maxmemory 的 80% 时预警。
  • 检查连接数:接近 maxclients 的 70% 时预警。
  • 检查主从延迟:slave_lag 超过 5 秒预警。

每周检查

  • 执行一次慢查询分析:`SLOWLOG GET 200`,识别并优化高频慢命令。
  • 检查大 key:使用 `redis-cli --bigkeys` 或自定义脚本扫描。
  • 检查持久化状态:rdb_last_bgsave_status 和 aof_last_rewrite_status 是否为 OK。
  • 检查系统参数:vm.overcommit_memory、net.core.somaxconn、transparent_hugepage(建议关闭)。

每月检查

  • 检查 Redis 版本:是否有安全或性能修复的更新版本。
  • 检查配置变更:对比当前配置与基线配置,确认是否有未记录的修改。
  • 检查数据增长趋势:根据 used_memory 的月增长率,预测未来 3-6 个月是否需要扩容。
  • 检查备份恢复演练:从 RDB 或 AOF 文件恢复数据,验证备份文件可用性。

季度检查

  • 检查架构设计:当前 Redis 部署模式(单机、哨兵、集群)是否仍满足业务增长需求。
  • 检查资源规划:是否需要增加分片、升级实例规格或迁移到更高性能的硬件。
  • 检查安全配置:是否启用了密码认证(requirepass)、是否限制了危险命令(rename-command FLUSHALL "")。

长期治理:构建可复用的故障响应流程

单次排查只能解决眼前问题,长期治理需要建立制度化的流程。

首先,建立故障分类标签库。将每次故障按类型(连接、内存、延迟、持久化、复制)和严重等级(P0-P3)记录,积累足够样本后,可以发现系统薄弱环节。例如,如果每月都出现连接数耗尽,说明连接池配置或容量规划存在系统性问题。

其次,制定标准操作手册(SOP)。对每种故障类型,编写清晰的排查步骤、恢复命令和验证方法。SOP 应包含回退方案,即恢复操作失败后的备选计划。例如,主从延迟的 SOP 中,如果调整 repl-backlog-size 无效,下一步是检查主库的写入源是否存在异常流量。

最后,定期进行故障演练。每季度至少一次,在预发环境模拟 Redis 故障(如模拟主库宕机、模拟内存写满),验证 SOP 的有效性和团队的响应速度。演练后形成改进项,持续更新 SOP。

在 SystemDo 参与过的多个企业项目中,我们发现:故障排查效率最高的团队,不是技术最强的团队,而是证据保留最完整的团队。每次故障后,花 15 分钟整理一份“故障复盘+证据归档”,长期坚持下来,多数常见故障都能在 10 分钟内定位根因。

总结:故障排查的核心原则

Redis 缓存服务的故障排查,核心在于三点:有基线、留证据、建流程。没有基线就无法判断异常程度;不留证据就会丢失关键线索;不建流程就只能每次从零开始。

上述故障类型和排查顺序,覆盖了生产环境中 90% 以上的 Redis 问题。但需要强调的是,每套系统的业务模型、数据规模、部署架构都不同,本文提供的排查步骤需要结合自身环境调整。例如,一个每秒处理 10 万次写入的金融系统,其故障排查的重点和优先级与一个日均请求量不足 1 万的内部管理系统完全不同。

最后,如果团队缺乏专职运维人员,建议优先使用云托管的 Redis 服务(如阿里云 Redis、AWS ElastiCache),其自动故障转移、自动备份、监控告警功能可以大幅降低运维负担。自建 Redis 虽然成本更低,但需要投入足够的运维资源,否则故障恢复时间可能远超预期。