内存淘汰策略不是缓存更新策略,它仅在maxmemory达到且新写入时被动腾出内存,无业务语义、不可控、不保一致;高一致性场景必须用cache aside模式(先改db再删缓存)+ ttl兜底。

内存淘汰策略不是缓存更新策略
Redis 的 maxmemory + 淘汰策略(如 allkeys-lru)只负责“腾地方”,不负责“保一致”。它不会主动感知数据库变更,也不会触发下游业务逻辑。把它当缓存更新手段,等于把数据一致性交给运气。
常见错误现象:写完数据库后没删缓存,缓存又刚好被淘汰了,下次读取反而从 DB 加载旧值再写入——看似“更新”了,实则固化了脏数据。
- 内存淘汰触发时机不可控:只在
maxmemory达到且新写入发生时才执行 - 淘汰对象无业务语义:
volatile-lfu可能干掉刚写入的热 key,allkeys-random完全随机 - 无法配合写操作节奏:你改了一条订单状态,它却淘汰了另一条用户配置
高一致性场景必须用 Cache Aside + TTL 兜底
真正可控的更新路径是:先改 DB,再删缓存(不是更新),读时重建。此时 maxmemory 淘汰和 EXPIRE 是两层独立防线,作用不同:
-
maxmemory控制物理内存上限,防 OOM;淘汰只是副作用,不是更新逻辑的一部分 -
EXPIRE是主动设置的保底机制,比如给店铺详情加3600秒 TTL,确保最坏情况下 1 小时内能自动刷新 - 删缓存动作必须在 DB 写成功后执行,建议用事务或补偿任务保障原子性(例如监听 binlog 或用 RocketMQ 延迟重试)
示例伪代码:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
db.update(order_id, status);<br>redis.del("order:" + order_id); // 不是 set,是 del<br>redis.expire("order:" + order_id, 3600); // 读时再 set 并重设 TTL
低频只读数据可直接依赖内存淘汰
像全国城市列表、商品类目树这类几乎不变更、且允许短暂不一致的数据,可以跳过主动删缓存逻辑,只靠 maxmemory-policy allkeys-lru + 大 TTL(如 24h)混用。
- 优势:省去所有缓存维护代码,DB 只读,服务更轻量
- 风险点:如果某次批量导入导致缓存集中失效,可能引发瞬时 DB 查询洪峰
- 关键参数要调:把
maxmemory设为实际可用内存的 70%~80%,避免系统级 swap
别让淘汰策略掩盖写操作缺陷
线上观察到缓存命中率突然下跌,第一反应不该是调大 maxmemory,而是查三件事:redis-cli --stat 看 evicted_keys 是否突增、慢日志里有没有大 value 写入、应用层是否漏掉了 DEL 调用。
很多团队把 allkeys-lru 当成“自动清理缓存”的捷径,结果 DB 更新了 10 分钟,缓存还在返回旧数据——因为淘汰没触发,TTL 还剩 59 分钟,而主动更新逻辑根本不存在。










