redis内存满后拒绝写入的根本原因是maxmemory-policy为noeviction时无法腾出空间,触发oom错误;启用allkeys-lru、volatile-lru、allkeys-lfu、volatile-ttl等主动淘汰策略可避免拒绝写入。

Redis内存满后拒绝写入的根本原因
Redis在maxmemory设限后,一旦实际内存占用达到该阈值,且当前配置的maxmemory-policy无法立即腾出空间(比如策略是noeviction),就会直接返回OOM command not allowed when used memory > 'maxmemory'错误,拒绝所有写命令(包括SET、LPUSH等)。
这不是Bug,而是设计使然:Redis默认优先保障数据一致性与响应确定性,不希望因后台异步淘汰导致写入行为不可预测。
哪些maxmemory-policy能避免拒绝写入
只有启用“主动淘汰”类策略,才能在内存满时自动驱逐旧数据,从而让新写入继续成功。关键看策略是否带eviction能力:
-
allkeys-lru:从全部key中淘汰最久未使用的——适合读写均匀、无明显冷热区分的场景 -
volatile-lru:只淘汰带过期时间的key——适合你用EXPIRE控制生命周期的缓存 -
allkeys-lfu:按访问频次淘汰——比LRU更能适应周期性热点,但内存开销略高 -
volatile-ttl:优先淘汰剩余TTL短的key——适合有明确时效分级的队列类缓存
而noeviction(默认值)、allkeys-random、volatile-random三者中,只有noeviction会硬性拒绝写入;后两者虽会随机删key,但删除不可控,生产环境极少使用。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
调整策略前必须确认的三件事
改maxmemory-policy不是改个配置就完事,容易踩坑:
- 确认你的key是否都设置了
EXPIRE——如果选了volatile-*策略但大量key没过期时间,等于“可淘汰池”为空,结果还是触发noeviction逻辑 - 检查淘汰是否真在发生——连上Redis执行
INFO memory,观察evicted_keys是否持续增长;为零说明策略没生效或没触发条件 - 注意LFU的计数器精度——
lfu-log-factor和lfu-decay-time会影响淘汰准确性,默认值在低频访问场景下可能导致“该淘汰的没淘汰”
线上调整策略的安全操作顺序
不建议直接CONFIG SET maxmemory-policy xxx,尤其在高负载时:
- 先用
CONFIG GET maxmemory-policy和INFO memory记录当前状态 - 如果原策略是
noeviction,切到volatile-lru前,确保至少70%以上的key已通过SETEX或EXPIRE设过期时间 - 用
CONFIG SET修改后,立刻监控evicted_keys和used_memory_peak_human,5分钟内无变化,大概率配置未生效或数据特征不匹配 - 若需长期稳定,把策略写进
redis.conf并重启(避免CONFIG SET在故障恢复后丢失)
淘汰策略不是万能解药——它解决的是“写不进去”,但掩盖了“为什么内存涨这么快”。真正要盯的,是mem_allocator分配器行为、bigkey堆积、客户端连接泄漏这些底层问题。










