线上 Redis 爆机排查与优化:从 CPU 飙高到内存溢出的完整救火指南

线上 Redis 爆机排查与优化:从 CPU 飙高到内存溢出的完整救火指南

线上 Redis 机器突然“爆机”,导致服务卡顿甚至当机,是运维和开发人员常遇到的紧急状况。面对这种情况,许多人的第一反应是硬件性能不足,急于增加内存或 CPU。然而,在绝大多数情况下,Redis 的性能瓶颈并非源于硬件,而是由不合理的代码逻辑或配置错误引起。

Redis 作为高性能内存数据库,本身具备极高的并发处理能力。一旦它出现“撑不住”的现象,通常是因为某些危险操作耗尽了系统资源。本文将梳理一套完整的线上救火与优化流程,帮助你在紧急情况下快速定位问题,并通过合理的配置与代码调整根治隐患。

`` 是摘要与正文的分隔标记,请保留。

识别“爆机”的四种典型场景

要解决问题,首先必须明确“爆了”具体指代什么。在真实的监控面板上,Redis 异常通常表现为四种截然不同的现象,每种现象对应的急救方案也完全不同,不能一概而论:

  1. CPU 使用率瞬间飙升至 100%
    • 原因:通常是因为执行了复杂度极高的慢命令(Slow Commands)。
    • 特征:主线程被长时间占用,导致其他请求无法处理。
  2. 内存耗尽(OOM)
    • 原因:存储了大量未设置过期时间的数据,或者产生了严重的内存碎片。
    • 特征:内存使用率接近上限,触发 Out Of Memory 错误。
  3. 网络带宽跑满
    • 原因:一次性传输了体积巨大的数据包。
    • 特征:网络 I/O 成为瓶颈,导致响应延迟增加。
  4. 连接数爆满
    • 原因:客户端程序存在 Bug,未能正常释放连接,导致连接池耗尽。
    • 特征:新请求无法建立连接,出现连接拒绝错误。

Redis爆机四种典型场景

核心原理:单线程模型下的“单行道”效应

为什么一个小小的命令或稍大的数据就能拖垮整台机器?这需要从 Redis 的核心运行机制说起。

Redis 处理客户端命令时主要依赖单线程模型。你可以将其想象成一条只有一条车道的单行道,所有请求必须排队通过。

  • 正常情况:轻量级请求快速通过,车道畅通。
  • 异常情况:如果此时有一辆“装满货物的重型卡车”(即 Big Key 大 Key 或需要全库扫描的慢命令)开上了这条路,它会长时间占用车道。在此期间,后面所有的轻量级请求都只能干等,整个 Redis 实例相当于“卡死”。

这就是为什么生产环境对大 Key 和慢查询必须保持零容忍的原因。

单线程模型下的阻塞效应

第一步:紧急“把脉”与指标定位

线上救火的第一步是紧急查看当前状态。切勿盲目重启,而应通过监控工具查看具体指标,定位异常源头:

  • 若 CPU 飙高:立即检查慢查询日志(Slow Log),找出最近执行时间最长的命令。
  • 若内存异常:查看内存使用率和碎片率,判断是数据膨胀还是碎片问题。
  • 若网络或连接异常:查看当前的客户端连接数和每秒拒绝的连接数。

只有定位到具体的异常指标,才能对症下药。

紧急指标定位流程

关键排查:识别并替换危险命令

在检查慢查询日志时,如果发现罪魁祸首是 KEYS 命令,这通常是生产事故的最典型诱因。

为什么禁止使用 KEYS 命令?

KEYS 命令的作用是按模式匹配查找所有的键,但它会一次性扫描整个数据库。如果库中有上千万个数据,该命令可能需要执行数秒。在此期间,Redis 完全无法处理其他请求,导致服务不可用。因此,在生产环境中必须绝对禁止使用 KEYS 命令。

正确做法:使用 SCAN 命令

如果业务确实需要批量查找数据,应使用 SCAN 命令。

  • 机制:SCAN 就像一条可以暂停的流水线,每次只取出一小部分数据(例如 100 个)。
  • 优势:虽然总耗时可能与 KEYS 差不多,但它不会长时间霸占单线程。其他请求依然可以穿插执行,从而保证了整体服务的可用性。
  • 操作:需要不断重复调用 SCAN,直到取完所有数据。

KEYS与SCAN命令对比

内存优化:配置兜底与大 Key 治理

如果排查后发现不是 CPU 问题,而是内存耗尽引发的 OOM,仅靠临时加内存无法根治,必须从配置和代码层面进行治理。

1. 配置层面:设置内存上限与淘汰策略

  • 设置 maxmemory:限制 Redis 能使用的最大内存,防止其无限制增长导致整个系统崩溃。
  • 配置 maxmemory-policy:对于缓存场景,通常推荐 allkeys-lru(Least Recently Used)策略。该策略优先淘汰最近最少使用的数据,让系统自动清理冷数据,保证新的热数据能写入。

2. 代码层面:主动治理大 Key

  • 拆分大 Key:例如,将一个包含几十万条记录的大 Hash 结构,拆分成多个按天或按用户 ID 区分的小 Hash。
  • 异步删除:在删除大 Key 时,不要直接使用普通的 DEL 命令,而是使用 UNLINK 命令。UNLINK 会让后台线程慢慢清理内存,避免主线程被瞬间阻塞。

内存优化与大Key治理

总结

线上 Redis 机器“爆机”,本质上绝大多数情况不是硬件不行,而是使用姿势不对。下次遇到 Redis 报警,建议遵循以下流程:

  1. 定位:通过监控确定是 CPU、内存还是网络问题。
  2. 排查:检查是否存在大 Key 或危险命令(如 KEYS)。
  3. 根治:通过合理的配置(内存限制、淘汰策略)和代码优化(拆分 Key、异步删除)来解决问题。

把单行道上的“重型卡车”拆成“小推车”,你的 Redis 就能真正发挥出应有的高性能。