Redis 缓存淘汰风暴与性能深度优化实战
很多站长、后端运维同学在使用Redis做站点缓存时,都会遇到一类很头疼的现象:缓存数据慢慢堆积,内存持续上涨,Redis却迟迟不主动清理;等到某一瞬间大量新缓存写入,才一次性触发大批量key淘汰,这时写入延迟飙升,网站页面直接卡顿。这就是典型的Redis内存淘汰风暴。
本文结合实际业务场景,先拆解这个问题的根源,再给出一套完整可落地的Redis性能优化方案,适合个人站点、资讯CMS、导航站这类业务直接参考配置。
一、先搞懂:为什么会出现淘汰风暴?
Redis默认的内存淘汰逻辑是惰性淘汰:只有当执行写入命令、检测到内存已经超过maxmemory上限时,才会开始淘汰key。
缓存慢慢涨,内存逐步逼近上限,但没有新写入请求 → Redis不会主动清理旧key,脏数据、冷数据持续占用内存;
当一波突发流量过来,大批量缓存写入,瞬间触达内存阈值;
Redis需要同步淘汰大量过期/冷key才能腾出空间,淘汰操作和写入抢CPU,命令阻塞,请求延迟暴涨,页面卡顿。
重点:不是key过期就自动删除。Redis的过期key本身也是惰性删除+定时随机采样删除,定时采样力度很弱,大量冷key堆积时,内存很容易一直占满。
二、针对淘汰风暴的专项调优方案
1. 基础核心配置(redis.conf)
# 设置最大可用内存,根据服务器内存预留系统、数据库内存,不要占满整机 maxmemory 4g # 推荐淘汰策略:优先淘汰最近最少使用的key,站点缓存最常用 maxmemory-policy allkeys-lru # 每次淘汰采样的key数量,默认5,调高一点,淘汰更均匀,避免单次扫大量key maxmemory-samples 10
策略选择说明:
allkeys-lru:所有key里淘汰最少使用,适合页面缓存、资讯缓存;volatile-lru:只在设置了过期时间的key里淘汰,如果很多缓存没加TTL,不推荐;尽量不要用
noeviction,内存满了直接拒绝写入,业务直接报错。
2. Redis7.0+ 平滑淘汰(重点,解决风暴神器)
Redis 7.0 新增了后台渐进式淘汰,可以把淘汰任务放到后台异步线程,不再和主线写入命令争抢资源,从根源避免单次大量淘汰阻塞主线程:
# 开启后台淘汰 lazyfree-lazy-eviction yes
同时配套开启其他懒释放:
lazyfree-lazy-expire yes lazyfree-lazy-server-del yes replica-lazy-flush yes
注意:低版本Redis(5/6)没有后台淘汰能力,只能靠业务侧限流、拆分缓存、缩短TTL来缓解。
3. 业务侧兜底方案(配置解决不了的,业务补)
给所有缓存key强制加上TTL,不要存在永久不过期的缓存,减少冷数据无限堆积;
大key拆分:页面渲染缓存、列表缓存如果很大,拆成小key,淘汰单key成本更低;
预热+限流:爬虫高峰、发布高峰做写入限流,避免瞬间大批量写缓存;
定时巡检脚本:低版本Redis可以写简单脚本,定时扫描、主动清理长期不访问的冷key,提前消化内存压力,不要等到内存满了再处理。
三、Redis 全维度性能优化清单
解决完淘汰风暴,我们再从内存、命令、持久化、内核网络、架构、监控几个维度做完整性能优化。
1. Key与命令优化
拒绝大key:大string、超大hash/list会造成删除、淘汰、序列化耗时高,尽量拆分;
避免高危命令:线上业务禁止线上使用
KEYS *,扫描全库用SCAN;批量操作优先用管道Pipeline、HMGET等,减少网络往返次数;
合理使用数据结构:计数用String,对象属性用Hash,排行榜用ZSet,不要乱用结构。
2. 持久化调优(非常影响写入性能)
RDB和AOF是性能消耗大户,站点缓存场景按需取舍:
纯缓存场景:数据丢了可以从数据库重新生成,可以关闭AOF,只保留RDB,或者降低RDB触发频率;
需要数据可靠性:AOF设置
appendfsync everysec,不要always
(每次写都刷盘,性能极差);
appendonly yes appendfsync everysec no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
3. 操作系统&内核参数
# 关闭透明大页,Redis经典坑,容易造成延迟抖动 echo never > /sys/kernel/mm/transparent_hugepage/enabled # 调高文件句柄,高流量站点容易报打开文件过多 ulimit -n 65535 # tcp调优,减少TIME_WAIT堆积 net.ipv4.tcp_tw_reuse = 1
宝塔面板部署Redis的同学,记得单独给Redis进程做资源限制,不要和MySQL、Nginx抢内存。
4. 架构层面优化
读写分离:主节点负责写入,从节点承接缓存查询,分流读压力;
分片集群:缓存体量很大时,用Redis Cluster分片,单实例内存不用拉很高,单个分片淘汰压力变小;
本地缓存+Redis二级缓存:热点页面、高频访问数据,在程序内部加本地内存缓存,减少Redis请求。
5. 监控告警,提前发现隐患
需要持续监控这几个核心指标:
used_memory、used_memory_peak:内存增长趋势;evicted_keys:淘汰key速率,突然暴涨就是风暴前兆;latency:命令延迟;expired_keys:过期删除数量; 告警规则:内存持续上涨、evicted_keys突增、平均延迟飙升,提前介入清理,不要等用户反馈页面卡顿。
四、总结
Redis缓存卡顿,很多时候不是Redis本身慢,而是淘汰机制的惰性特性带来的集中清理风暴。 优先顺序建议:
规范业务,所有缓存加TTL,消灭永久缓存、大key;
调整maxmemory、淘汰采样数、选择合适LRU策略;
升级到Redis7.0,开启lazyfree后台渐进淘汰,这是最有效的手段;
配合持久化、内核、读写架构优化;
搭建监控,提前感知内存上涨,主动清理冷数据。
这套方案非常适合资讯站、CMS、导航站这类依赖Redis做页面缓存的个人站点,改动可控,不需要大幅改业务代码,就能明显缓解流量高峰下的页面卡顿问题。










发表评论