首页 > 基础资料 博客日记
线上 Redis 突然“爆”了,怎么办?
2026-06-11 19:00:01基础资料围观1次
凌晨三点,手机疯狂报警——Redis CPU 100%,内存快满了,业务接口一个个超时……
别慌,这篇文章不堆术语,我会像聊天一样,带你一步步排查问题、稳住现场、顺便把优化思路讲清楚。
一、先搞清楚“爆”是什么意思?
“机器爆了”通常指以下几种情况,不同情况处理方式不一样:
| 现象(你能看到什么) | 最可能的原因 |
|---|---|
| CPU 使用率 100% | 请求太多、执行了慢命令(比如 KEYS *)、或者 Redis 在做持久化 |
| 内存快用完了 | 存了太多数据、很多 key 没设过期时间、或者内存碎片太多 |
| 连接数爆满 | 客户端程序没释放连接、连接池设置不合理 |
| 网络跑满 | 传输了大 key(比如一个 value 几 MB),或者一次取太多数据 |
| 响应变慢、卡顿 | 有慢查询、或者 Redis 在做 fork 操作(比如生成快照) |
小解释
- fork:Redis 保存数据到硬盘时,会复制自己一份(子进程),这个过程会短暂卡一下。
- 大 key:指单个 key 对应的 value 非常大,比如一个 hash 里存了 10 万条数据。
- 慢查询:执行时间超过预设阈值(比如 10 毫秒)的命令。
二、第一步:紧急“把脉”——查看当前状态
登录到出问题的机器,执行下面几条命令(不用记,收藏就行):
# 看 Redis 进程占用了多少 CPU 和内存
top -p $(pgrep redis-server)
# 连上 Redis 看关键指标
redis-cli INFO stats # 每秒请求数、拒绝连接数等
redis-cli INFO memory # 用了多少内存、碎片率
redis-cli INFO clients # 当前有多少客户端连接
redis-cli SLOWLOG GET 10 # 抓出最近的慢命令
如果发现 SLOWLOG 里有一堆 KEYS *,那恭喜你,找到元凶了。下面我们专门讲它。
三、场景一:CPU 飙高 —— 重点讲 KEYS 和 SCAN
3.1 KEYS 命令:方便但危险
它有什么用?
KEYS pattern 可以查出所有匹配某个模式的 key。
比如你想找所有以 user: 开头的 key:
redis-cli KEYS "user:*"
它有什么问题?
它会一次性扫描整个数据库,把所有 key 都查一遍。如果库里有 1000 万个 key,这个命令可能要执行好几秒,期间 Redis 无法处理其他请求,CPU 瞬间爆满。生产环境禁止使用!
比喻:就像在一个巨大仓库里,不用索引,挨个箱子翻找所有带“用户”标签的箱子,而且翻完之前不能做任何其他事。
3.2 代替方案:SCAN 命令——温和的游标扫描
SCAN 像一条“可暂停的流水线”:每次只取一小部分(比如 100 个),你需要不断重复调用,直到取完所有数据。虽然麻烦一点,但不会阻塞 Redis。
基本用法:
# 第一次扫描:从游标 0 开始
redis-cli SCAN 0 MATCH "user:*" COUNT 100
# 返回:1) "下一轮的游标值" 2) ["user:1", "user:2", ...]
如果返回的游标是 0,说明扫描结束;否则用这个游标继续:
redis-cli SCAN <上一轮返回的游标> MATCH "user:*" COUNT 100
注意:
COUNT只是建议每批返回的数量,不保证精确。通常设为 100~1000 即可。
代码示例(Python):
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
# 处理每个 key
pass
if cursor == 0:
break
这样优化后:原本一个 KEYS 造成的 5 秒阻塞,被拆成几十次毫秒级的扫描,CPU 平稳,用户几乎无感知。
3.3 其他 CPU 杀手及解决
| 问题命令 | 替代方案 |
|---|---|
HGETALL 大 hash |
用 HSCAN 分批取 |
SMEMBERS 大 set |
用 SSCAN 分批取 |
ZRANGE 取全量 |
加上 LIMIT 分页 |
SORT 操作 |
尽量在客户端或数据库做排序 |
另外如果整体 QPS(每秒请求数)太高,比如超过 5 万,考虑:
- 加从库做读写分离(读请求走从库)
- 使用 Redis Cluster 把数据分到多台机器
QPS:Queries Per Second,每秒查询次数。
四、场景二:内存快满了 —— 先看谁吃掉了内存
4.1 快速找出“大 key”
Redis 自带了扫描大 key 的工具:
redis-cli --bigkeys
它会告诉你哪种类型的 key 占内存最多,比如:
- 最大的 10 个 string
- 元素最多的 hash / set / list
解决办法:
- 给 key 加上过期时间:
EXPIRE keyname 3600(1 小时后自动删除) - 拆分大 key:比如把一个有 10 万字段的 hash,拆成 100 个小 hash,按 id 分段
- 压缩 value:存 JSON 之前先用 gzip 压缩(会略微增加 CPU,但省内存)
4.2 内存碎片是什么?怎么清理?
解释:你删掉了 10 个 key,但 Redis 并没有把内存立刻还给操作系统,留下很多“小空洞”,导致实际占用的内存(used_memory_rss)远大于你真正使用的内存(used_memory)。
查看碎片率:
redis-cli INFO memory | grep mem_fragmentation_ratio
如果大于 1.5,说明碎片比较严重。
处理办法:
- 重启 Redis(最简单粗暴,但会短暂停服)
- 如果用的是 Redis 4.0 以上,可以执行
MEMORY PURGE尝试整理 - 调整内存分配器(通常用 jemalloc 会好一些)
4.3 设置内存上限和淘汰策略
一定要给 Redis 设置最大内存,否则它会一直吃直到机器死机。
# 最大用 8GB
CONFIG SET maxmemory 8gb
# 内存满了怎么办?按 LRU(最近最少使用)算法淘汰旧数据
CONFIG SET maxmemory-policy allkeys-lru
LRU:Least Recently Used,淘汰那些很久没被访问的 key。
其他策略:volatile-lru(只淘汰有过期时间的 key)、noeviction(满了就拒绝写入)等。
五、场景三:连接数爆了 —— 客户端没“分手”
现象:redis-cli INFO clients 显示 connected_clients 接近一万,并且出现 ERR max number of clients reached。
原因:你的应用程序每次请求都新建连接,用完却不关闭;或者连接池配置了“永不超时”。
优化:
- 在 Redis 配置中设置空闲连接超时:
timeout 300(300 秒无活动就断开) - 检查代码:使用连接池(如 JedisPool、Lettuce),并设置
maxTotal和maxIdle - 如果瞬间涌入大量客户端(比如抢购),可以在前面加一层代理(如 Twemproxy)来聚合连接
六、场景四:网络带宽打满 —— 传了太多“大包裹”
现象:网卡流量跑满,Redis 吞吐量下降。
常见原因:有人一次性读了一个几 MB 的 key,并且频繁操作。
排查:可以用 redis-cli --bigkeys 找到最大的那些 key,看是不是业务在反复读写。
优化:
- 避免一个 value 超过 1 MB,如果必须大 value,考虑压缩
- 使用
MGET时,一次不要超过 100 个 key - 启用 RESP3 协议(Redis 6 以上)可减少网络往返
七、事后要做的“长期优化”
救火之后,得治本。
7.1 架构级改造
- 分片:用 Redis Cluster 把数据分散到多个节点,每个节点只存一部分。
- 读写分离:主库写,从库读,分担压力。
- 多级缓存:热点数据放到本地内存(比如 Caffeine),访问 Redis 的频率自然就降下来了。
7.2 监控告警(这次不能再裸奔了)
至少监控这些指标:
- CPU 使用率
- 内存使用率 + 碎片率
- 慢查询数量
- 命中率(
keyspace_hits / (keyspace_hits+keyspace_misses),低于 0.8 说明缓存效果差) - 主从复制延迟
推荐工具组合:Prometheus + Grafana + redis_exporter,配置好告警规则。
7.3 定期巡检(每季度一次)
- 执行
SLOWLOG GET 100分析慢查询 - 检查有没有
KEYS被误用(通过监控慢日志) - 找出长期不用的 key,批量删除
八、如果 Redis 已经“爆”了,应急三招
-
临时牺牲数据一致性
如果内存爆满,紧急执行CONFIG SET maxmemory-policy allkeys-lru让 Redis 自己淘汰旧数据,尽快恢复服务。 -
流量切换
如果有备用 Redis 集群,立刻通过 DNS 或负载均衡切一部分流量过去。 -
应用层限流
在代码里加个限流器:每秒最多向 Redis 发 5000 次请求,超过的直接返回缓存空值或降级数据。
最后说几句
Redis 优化没什么玄学,记住三句话:
- 不给 Redis 添乱:不用
KEYS、不存大 key、记得设过期时间。 - 资源要设上限:
maxmemory一定要配,淘汰策略要选对。 - 监控要早:别等到半夜被报警吵醒才想起来。
如果你在实际中遇到过更奇葩的“爆机”案例,欢迎评论区分享,我们一起排雷。
附录:本文提到的专业词汇速查表
| 词汇 | 简单解释 |
|---|---|
| KEYS 命令 | 遍历所有 key 的命令,会阻塞 Redis,生产环境禁用 |
| SCAN 命令 | 游标式遍历,每次取一小批,不阻塞 |
| 慢查询 | 执行时间太长的命令,会被记录到 SLOWLOG 里 |
| QPS | 每秒请求数,衡量 Redis 的压力 |
| 内存碎片 | 内存被删得七零八落,实际占用比数据多 |
| LRU | 淘汰最近最少使用的 key |
| fork | Redis 持久化时复制自身进程,可能短暂卡顿 |
| RESP3 | Redis 新版协议,更节约网络流量 |
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:

