Redis内存满了怎么办?

张开发
2026/4/14 15:34:35 15 分钟阅读

分享文章

Redis内存满了怎么办?
Redis内存满了怎么办从过期策略到淘汰机制一篇讲透摘要Redis作为高性能内存数据库内存资源是有限的。当Redis内存使用达到上限maxmemory时会发生什么如何避免OOM本文将深入剖析Redis的过期键删除策略、内存淘汰机制并给出生产环境的最佳实践配置。1. 前言为什么Redis需要管理内存Redis将所有数据存储在内存中以换取极高的读写速度。但内存成本高、容量有限如果不加控制恶意写入或业务增长都可能导致内存耗尽进而引发服务崩溃或被操作系统OOM Killer杀掉。因此合理设置内存上限并配置淘汰策略是Redis生产环境必备的稳定性手段。2. 设置内存上限maxmemory在redis.conf或通过CONFIG SET动态配置# 设置最大内存为4GB单位可以是bytes, kb, mb, gbmaxmemory 4gb64位系统默认maxmemory0表示无内存限制可能导致内存无限增长最终被系统kill。建议值物理内存的3/4剩余留给操作系统和子进程如RDB/AOF重写。32位系统最大支持3GB默认maxmemory3GB。3. Redis的过期键删除策略当键设置了过期时间TTLRedis如何删除它实际采用的组合是定期删除 惰性删除。注意并没有使用“定时删除”因为创建大量定时器会严重影响性能。下面分别说明三种理论策略并指出Redis的实现选择。3.1 三种删除策略对比策略原理优点缺点Redis采用定时删除设置键过期时创建一个定时器到期立即删除内存友好及时释放CPU开销大大量定时器影响性能❌ 不采用惰性删除访问键时检查是否过期过期则删除CPU友好只在实际访问时检查可能长期占用内存过期但一直未访问的key✅ 采用定期删除每隔一段时间默认100ms随机抽样过期key并删除平衡CPU与内存仍有部分过期key残留✅ 采用3.2 Redis实际工作流程是否过期未过期是否客户端写入数据键是否设置TTL?存入过期字典普通存储定期删除任务启动每100ms随机抽取一批带过期时间的key检查是否过期删除key保留客户端读取某个key惰性删除检查该key是否过期?立即删除并返回nil正常返回值内存达到maxmemory触发内存淘汰机制关键点定期删除默认每秒执行10次可通过hz参数调整每次随机抽取一批设置了过期时间的key删除其中过期的。不会全量扫描避免阻塞主线程。惰性删除当客户端读取key时先检查是否过期过期则删除并返回空。两者配合定期删除清理大部分过期key惰性删除兜底。但仍有极端情况一些过期key从未被访问且定期删除未抽中会长期占用内存 → 此时需要内存淘汰机制兜底。4. 内存淘汰机制最后的防火墙当maxmemory达到上限后Redis会根据配置的淘汰策略来腾出空间给新写入。这是内存快满时的“紧急通道”。4.1 触发时机每次执行命令如set、lpush等导致内存增加时检查是否超过maxmemory。若超过则按照所选策略逐出一些key直到内存低于上限。4.2 八种淘汰策略Redis 4.0策略作用范围行为描述noeviction所有key内存满时写入操作返回错误默认策略allkeys-lru所有key使用LRU算法淘汰最近最少使用的keyvolatile-lru设置了过期时间的key在有过期时间的key中淘汰LRU的keyallkeys-lfu所有key使用LFU算法淘汰最不经常使用的keyRedis 4.0新增volatile-lfu设置了过期时间的key在有过期时间的key中淘汰LFU的keyallkeys-random所有key随机淘汰volatile-random设置了过期时间的key在有过期时间的key中随机淘汰volatile-ttl设置了过期时间的key淘汰剩余TTL最短的keyLRULeast Recently Used最近最少使用LFULeast Frequently Used最不经常使用访问频率4.3 LRU/LFU近似算法Redis并没有采用精确的全局LRU太耗内存而是近似LRU随机采样N个key默认maxmemory-samples 5淘汰其中空闲时间最长的。采样数越大淘汰越精确但CPU开销越大。4.4 如何选择淘汰策略场景推荐策略缓存场景数据可从DB重建allkeys-lru或allkeys-lfu部分数据不能淘汰如用户会话volatile-lru并只给可淘汰的key设置过期时间有冷热数据明显区分allkeys-lfu无任何数据可淘汰宁可写失败noeviction金融/强一致性场景慎用5. 配置与监控5.1 动态配置淘汰策略# 设置淘汰策略redis-cli configsetmaxmemory-policy allkeys-lru# 设置内存上限redis-cli configsetmaxmemory 8gb# 设置LRU采样数量可选redis-cli configsetmaxmemory-samples105.2 监控内存状态redis-cli info memory重点关注used_memory_human实际使用内存maxmemory_human配置上限mem_fragmentation_ratio碎片率1.5需关注evicted_keys因内存淘汰被删除的key总数5.3 最佳实践建议生产环境务必设置maxmemory建议为物理内存的70%~80%留出内存给系统及fork子进程。默认策略是noeviction不做配置会导致内存满后写失败业务异常。应根据场景显式配置。给key合理设置过期时间配合volatile-*策略更灵活。调高采样数如10提升LRU/LFU精度但增加CPU消耗。监控evicted_keys如果淘汰频繁说明内存不足或过期时间设置不合理需扩容或优化数据。6. 完整流程图从写入到淘汰读取请求是否客户端读操作惰性删除检查key过期?删除并返回nil返回value后台清理定期删除任务抽样过期key删除过期key写入请求是否客户端写操作内存是否超过maxmemory?执行淘汰策略逐出key写入新key7. 总结机制作用触发时机定期删除主动清理过期key每100ms一次惰性删除访问时删除过期key每次读/写该key内存淘汰内存达到maxmemory后强制逐出每次写操作前Redis通过定期惰性组合高效清理过期数据再通过内存淘汰机制作为最后防线确保内存不会越界。合理配置maxmemory和maxmemory-policy配合监控告警才能让Redis稳定运行在高压力之下。一句话记忆定期清、惰性删、满则逐LRU/LFU三管齐下保平安。

更多文章