Redis 内存打满、连接数飙红?运维排查四步法

导语:应用突然大量报错,日志里写着 OOM command not allowed when used memory > 'maxmemory',或者 ERR max number of clients reached。登上去 redis-cli 敲什么都超时------这是 Redis 运维最常见的两种"猝死"。别急着重启,按下面四步走,先定位再处置。

一、第 1 步:先分清是"内存满"还是"连接满"

两种故障的排查路径完全不同,第一步必须分开看。

yaml 复制代码
redis-cli -h 10.0.0.10 -p 6379
# 内存视图
INFO memory
#   used_memory_human        已用内存(数据集+开销)
#   used_memory_rss_human    操作系统看到的常驻内存
#   maxmemory_human          配置的上限
#   maxmemory_policy         淘汰策略
#   mem_fragmentation_ratio  碎片率
bash 复制代码
# 连接视图
INFO clients
#   connected_clients           当前连接数
#   blocked_clients             阻塞在 BLPOP 等的连接
#   client_recent_max_input_buffer / output_buffer

INFO stats
#   rejected_connections        因超 maxclients 被拒的连接数
#   evicted_keys                因内存淘汰被删的 key 数
#   expired_keys                已过期删除的 key 数

判读口径:

  • used_memory 顶到 maxmemory 且 evicted_keys 猛涨 → 内存问题。
  • connected_clients 逼近 maxclients、rejected_connections 不为 0 → 连接问题。
  • mem_fragmentation_ratio > 1.5 → 碎片严重;< 1 → 已经在用 swap,性能会断崖式下跌。

避坑 1 :maxmemory 设了但没设 maxmemory-policy,默认是 noeviction------写请求会直接报 OOM,而不是淘汰旧数据。这是"内存没满却写不进去"的头号原因。

二、第 2 步:找出谁在吃内存(大 key / 热点 key)

内存问题 90% 出在少数几个大 key 上。

bash 复制代码
# 按数据类型采样,找出每种类型最大的 key(Redis 自带,开销低)
redis-cli --bigkeys

# Redis 6.0+ 还可以按内存排序
redis-cli --memkeys

# 精确定位某个 key 的真实内存占用(含内部编码开销)
redis-cli MEMORY USAGE my:big:hash SAMPLES 0

找不到方向时,用 SCAN 分批采样统计,而不是 KEYS *:

vbnet 复制代码
# 抽样 1000 个 key,按前缀聚合数量,找"数量异常多"的业务前缀
redis-cli --scan --pattern 'order:*' --count 1000 | head -n 1000

# 找出大 hash / 大 zset 的元素个数
redis-cli HLEN order:detail:20261009001
redis-cli ZCARD rank:hot:global

热点 key 用 LFU 策略统计(需 maxmemory-policy 为 allkeys-lfu / volatile-lfu):

css 复制代码
redis-cli --hotkeys

避坑 2 :KEYS *、FLUSHALL、MONITOR 在生产环境一律禁用。前两个会阻塞主线程导致秒级卡死,MONITOR 会把所有命令广播给慢客户端,几分钟就能把内存打爆。

避坑 3 :--bigkeys 内部仍要遍历全库,请在业务低峰期执行;超大实例可先 --scan 估量。

三、第 3 步:看清内存到底花在哪

used_memory 不等于数据集,开销同样能吃人。

bash 复制代码
INFO memory
#   used_memory_dataset        纯数据占用
#   used_memory_overhead       客户端缓冲区、复制积压等开销
#   used_memory_peak_human     历史峰值
#   used_memory_lua            脚本

排查三个常被忽略的"隐形内存":

shell 复制代码
# 1) 客户端输出缓冲区:慢客户端(订阅、MONITOR、大结果集)会积压
redis-cli CLIENT LIST
# 关注 omem(输出缓冲区)、qbuf、idle 三列,omem 特别大的连接就是"慢客户端"

# 2) 主从复制积压区
INFO replication
#   repl_backlog_size 配置过大 / 从库长时间断连都会撑大内存

# 3) 过期 key 没被及时回收
INFO keyspace
#   expires 与 keys 的差值异常,说明大量 key 无 TTL

四、第 4 步:常见根因与处置

排查到最后,逃不出这五类:

  1. 缓存不设 TTL:业务写入的 key 永不过期,只增不减。给所有缓存 key 加过期时间,或改用带容量的本地缓存 + Redis 组合。
  2. 大 key:单个 hash/list/zset 存了几十万甚至上百万元素(如全量字典、排行榜、日志队列)。按业务维度拆分,或用 hash tag 分片。
  3. 客户端连接泄漏 :应用没复用连接池、异常分支忘了 close(),connected_clients 缓慢爬升。常见于短连接模式与定时任务。
  4. 输出缓冲区失控 :慢客户端订阅大频道、执行 MONITOR、KEYS,omem 飙到几百 MB。
  5. AOF rewrite / fork 抖动 :重写期间 COW 会额外占用内存,maxmemory 没留余量就会触发 OOM。

应急止血:先降载,别急着删

ini 复制代码
# 1) 临时改为 LRU 淘汰,先让写入活下来(注意会丢数据)
redis-cli CONFIG SET maxmemory-policy allkeys-lru

# 2) 删大 key 用 UNLINK(异步回收,不阻塞主线程),别用 DEL
redis-cli UNLINK order:detail:20260101

# 3) 批次删除,别一次删一堆
redis-cli --scan --pattern 'temp:*' --count 100 | xargs -L 100 redis-cli UNLINK

# 4) 断开空闲连接,清理连接泄漏
redis-cli CLIENT LIST | awk -F'idle=' '{split($2,a," "); if (a[1] > 3600) print $1}' | head
redis-cli CLIENT KILL ID <id>

长期治理:为实例设定 maxmemory(物理内存的 60%--75%,留出 fork 与 OS 空间)、显式配置淘汰策略、给所有缓存 key 加 TTL、把 used_memory、connected_clients、evicted_keys、rejected_connections 纳入监控告警(内存 > 80% 阈值、连接数 > 80% maxclients 提前预警)。

五、避坑清单

  1. KEYS * / FLUSHALL / MONITOR 生产禁用,改用 SCAN 与 INFO。
  2. 删大 key 用 UNLINK 而非 DEL,DEL 会阻塞主线程。
  3. 只设 maxmemory 不设 maxmemory-policy,默认 noeviction 会直接拒绝写入。
  4. maxmemory 不要设成物理内存全量:RDB 保存 / AOF 重写需要 fork,COW 要有余量。
  5. 主从实例的 maxmemory 应保持一致,从库更小会导致主从数据不一致。
  6. maxclients 受 OS 的 ulimit -n 限制,连接打满时先确认系统句柄数。
  7. 上线前做一次容量基线:单 key 元素上限、平均 value 大小、日均 key 增量,出问题才能判断"现在算不算异常"。

小结 :顺序记成一句话------INFO 分清内存/连接 → --bigkeys 揪大 key → INFO memory 看清开销构成 → 按五类根因处置,先 UNLINK 降载再治理 。Redis 排查的关键是"先看指标、再找 key、后动数据":不要一上来就重启或 FLUSHALL,把"内存涨了多少、是谁在涨、涨在数据集还是开销"三个问题回答清楚,元凶自然现形。

相关推荐
zly35002 小时前
centos7 mount设备挂载 /dev/sda1/硬盘挂载
linux·运维·服务器
零基础1232 小时前
FinalShell 使用教程:从安装到高效运维
运维·经验分享·笔记·finalshell
帷幕落秋2 小时前
Docker的两种安装
运维·docker·容器
fengkai45452 小时前
十二、Redis -2
运维·数据库·redis·容器
哎呦,帅小伙哦2 小时前
进程监控工具——htop
linux·运维·服务器
深圳恒讯3 小时前
海外服务器延迟高怎么解决?从线路到TCP协议的6层排查清单
运维·服务器·tcp/ip
北龙云海3 小时前
AI驱动数据库运维变革:北龙云海智能巡检平台实践与展望
运维·数据库·人工智能
AI职业加油站3 小时前
AI 校招现状:大模型应用工程师证书,助力简历能力证明
大数据·运维·人工智能·学习·职场发展
Lsetea5 小时前
curl报58 unable to set private key file:客户端证书与私钥加载排查
运维·https·ssl证书·openssl·curl