Redis 缓存淘汰风暴与性能深度优化实战

运维开发 2026-10-24 09:47:27 浏览 次

Redis 缓存淘汰风暴与性能深度优化实战

很多站长、后端运维同学在使用Redis做站点缓存时,都会遇到一类很头疼的现象:缓存数据慢慢堆积,内存持续上涨,Redis却迟迟不主动清理;等到某一瞬间大量新缓存写入,才一次性触发大批量key淘汰,这时写入延迟飙升,网站页面直接卡顿。这就是典型的Redis内存淘汰风暴。

本文结合实际业务场景,先拆解这个问题的根源,再给出一套完整可落地的Redis性能优化方案,适合个人站点、资讯CMS、导航站这类业务直接参考配置。

一、先搞懂:为什么会出现淘汰风暴?

Redis默认的内存淘汰逻辑是惰性淘汰:只有当执行写入命令、检测到内存已经超过maxmemory上限时,才会开始淘汰key。

  1. 缓存慢慢涨,内存逐步逼近上限,但没有新写入请求 → Redis不会主动清理旧key,脏数据、冷数据持续占用内存;

  2. 当一波突发流量过来,大批量缓存写入,瞬间触达内存阈值;

  3. 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. 业务侧兜底方案(配置解决不了的,业务补)

  1. 给所有缓存key强制加上TTL,不要存在永久不过期的缓存,减少冷数据无限堆积;

  2. 大key拆分:页面渲染缓存、列表缓存如果很大,拆成小key,淘汰单key成本更低;

  3. 预热+限流:爬虫高峰、发布高峰做写入限流,避免瞬间大批量写缓存;

  4. 定时巡检脚本:低版本Redis可以写简单脚本,定时扫描、主动清理长期不访问的冷key,提前消化内存压力,不要等到内存满了再处理。

三、Redis 全维度性能优化清单

解决完淘汰风暴,我们再从内存、命令、持久化、内核网络、架构、监控几个维度做完整性能优化。

1. Key与命令优化

  1. 拒绝大key:大string、超大hash/list会造成删除、淘汰、序列化耗时高,尽量拆分;

  2. 避免高危命令:线上业务禁止线上使用KEYS *,扫描全库用SCAN;

  3. 批量操作优先用管道Pipeline、HMGET等,减少网络往返次数;

  4. 合理使用数据结构:计数用String,对象属性用Hash,排行榜用ZSet,不要乱用结构。

2. 持久化调优(非常影响写入性能)

RDB和AOF是性能消耗大户,站点缓存场景按需取舍:

  • 纯缓存场景:数据丢了可以从数据库重新生成,可以关闭AOF,只保留RDB,或者降低RDB触发频率;

  • 需要数据可靠性:AOF设置appendfsync everysec,不要alwaysRedis缓存淘汰风暴与性能深度优化实战(每次写都刷盘,性能极差);

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. 架构层面优化

  1. 读写分离:主节点负责写入,从节点承接缓存查询,分流读压力;

  2. 分片集群:缓存体量很大时,用Redis Cluster分片,单实例内存不用拉很高,单个分片淘汰压力变小;

  3. 本地缓存+Redis二级缓存:热点页面、高频访问数据,在程序内部加本地内存缓存,减少Redis请求。

5. 监控告警,提前发现隐患

需要持续监控这几个核心指标:

  • used_memory、used_memory_peak:内存增长趋势;

  • evicted_keys:淘汰key速率,突然暴涨就是风暴前兆;

  • latency:命令延迟;

  • expired_keys:过期删除数量; 告警规则:内存持续上涨、evicted_keys突增、平均延迟飙升,提前介入清理,不要等用户反馈页面卡顿。

四、总结

Redis缓存卡顿,很多时候不是Redis本身慢,而是淘汰机制的惰性特性带来的集中清理风暴。 优先顺序建议:

  1. 规范业务,所有缓存加TTL,消灭永久缓存、大key;

  2. 调整maxmemory、淘汰采样数、选择合适LRU策略;

  3. 升级到Redis7.0,开启lazyfree后台渐进淘汰,这是最有效的手段;

  4. 配合持久化、内核、读写架构优化;

  5. 搭建监控,提前感知内存上涨,主动清理冷数据。

这套方案非常适合资讯站、CMS、导航站这类依赖Redis做页面缓存的个人站点,改动可控,不需要大幅改业务代码,就能明显缓解流量高峰下的页面卡顿问题。



本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐