直接原因是maxmemory-policy为noeviction;默认该策略下内存达maxmemory时所有写命令立即报oom错误,不淘汰、不警告;改allkeys-lru可快速兜底,因它能淘汰任意键而非仅带ttl的键。

写入失败直接原因是 maxmemory-policy 还是 noeviction,改成 allkeys-lru 是最快生效的兜底方案,但不是万能解药。
为什么 SET/LPUSH 会报 OOM 错误
错误信息 (error) OOM command not allowed when used memory > 'maxmemory' 不代表 Redis 崩了,只是策略卡死了。默认 noeviction 下,哪怕内存只超 1 字节,所有写命令(SET、LPUSH、HSET、INCR)全部拒绝——它不淘汰、不警告、不重试,纯硬拦截。
这不是客户端或网络问题,redis-cli 直连执行也会失败;也不是内存碎片导致,而是策略开关没打开。
- 用
redis-cli config get maxmemory-policy确认当前值是不是noeviction - 用
redis-cli info memory | grep -E "(used_memory|maxmemory)"看是否已触顶 - 如果
maxmemory返回0,说明根本没设上限,策略不生效,得先配maxmemory
allkeys-lru 比 volatile-lru 更容易起效
很多团队第一反应是切 volatile-lru,但它只淘汰带 EX/PX 的键。现实里大量缓存直写没设 TTL:SET cache:order:789 "data",这类键在 volatile-lru 下永远不参与淘汰,内存照样锁死。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
allkeys-lru 才真正覆盖全量键空间,只要内存超限,它就能动起来。
- 适合场景:通用缓存层、会话存储、热点数据临时聚合
- 不适用场景:把 Redis 当唯一状态库(比如用户余额)、强依赖“写完立刻能读到”的逻辑
- 低版本风险:Redis INFO stats 中的
evicted_keys可能滞后,建议升级
怎么安全地切到 allkeys-lru
运行时切策略快,但有隐含前提——你得先确认 maxmemory 已生效且非零。否则 CONFIG SET maxmemory-policy allkeys-lru 成功了,实际也压根不触发淘汰。
- 先检查:
redis-cli config get maxmemory,如果不是数字(如1073741824),立刻补:CONFIG SET maxmemory 1gb - 再切换:
CONFIG SET maxmemory-policy allkeys-lru(本次进程有效) - 永久生效:编辑
redis.conf,确保两行都存在:maxmemory 1gb<br>maxmemory-policy allkeys-lru
,然后redis-cli config rewrite或重启 - 验证是否生效:连续执行几次
SET testkey randval,观察INFO stats中evicted_keys是否递增
allkeys-lru 实际运行时的三个反直觉点
它不是“一写就删”,也不保证严格 LRU,更不会帮你兜住所有业务逻辑漏洞。
- 触发时机是“写前检查 + 后台周期扫描”,所以内存可能短暂冲高 3%~5%,
used_memory会略超maxmemory - 淘汰基于采样(默认 5 个 key 比较),不是全量排序——访问模式极端倾斜时(比如 95% 请求只打 5 个 key),冷数据可能被误删
-
GET刚SET的键可能返回 nil:因为淘汰发生在下一次写操作前,而你的读在写之间,中间没触发清理
真正关键的不是策略名,而是你有没有把 Redis 当缓存用——所有重要数据必须有下游持久化,所有写入失败路径必须有 fallback 逻辑。策略只是让服务不断,不是让数据不丢。










