redis的lru淘汰不会触发pub/sub事件,仅过期事件(需配置notify-keyspace-events ex)可监听;同步缓存失效应依赖ttl+keyspace通知,而非lru机制。

Redis 本身不提供“本地缓存同步”能力,LRU 淘汰机制只作用于单个 Redis 实例内部,无法跨进程、跨服务传播淘汰行为。想靠 maxmemory-policy allkeys-lru 触发 Pub/Sub 通知其他节点“这个 key 刚被淘汰了”,这条路走不通——Redis 不会为淘汰事件发消息。
Redis 的 LRU 淘汰不会触发任何 Pub/Sub 事件
这是最容易误解的一点。很多人以为只要配置了 allkeys-lru,key 被踢出时就能监听到。但事实是:DEL、EXPIRE、EVICT 这些底层淘汰动作,Redis 默认不对外广播。它只在明确的过期时刻(且启用了 keyspace notifications)向 __keyevent@<db>__:expired</db> 发布消息,而淘汰(eviction)不属于过期(expiration),两者机制完全独立。
-
EXPIRE/SET ... EX→ 可能触发expired事件(需配置notify-keyspace-events Ex) -
LRU淘汰 → 完全静默,无 channel、无日志、无回调 - 即使你用
redis-cli --stat看到evicted_keys在涨,也拿不到具体是哪个 key
想同步“被 LRU 踢掉的 key”,得自己埋点拦截
如果你真需要让其他服务知道“某个 key 刚从本机 Redis 缓存里消失了”,必须绕开淘汰机制,改用显式控制:
- 不依赖自动淘汰,改用带 TTL 的
SET key value EX 300主动设过期时间 - 提前配置好 keyspace notifications:运行
CONFIG SET notify-keyspace-events Ex(或写进redis.conf) - 监听
__keyevent@0__:expired(注意 db 编号要匹配) - 收到消息后,解析 payload(是 key 名),再通过自定义 channel(如
cache-evict-broadcast)用PUBLISH推给其他节点
示例监听逻辑(Python):
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
import redis<br>conn = redis.Redis()<br>pubsub = conn.pubsub()<br>pubsub.subscribe('__keyevent@0__:expired')<br><br>for msg in pubsub.listen():<br> if msg['type'] == 'message':<br> key = msg['data'].decode()<br> # 这里不是淘汰,是过期;但语义上可当作“缓存失效”处理<br> conn.publish('cache-invalidation', key)
Pub/Sub 同步缓存失效,别碰 LRU,盯紧 TTL + keyspace events
真正可行的路径是放弃“同步淘汰”,转向“同步失效”:
- 所有写操作统一走
SET key value EX N或PEXPIRE,不用maxmemory压力测试式淘汰 - 确保所有 Redis 实例都开启
notify-keyspace-events(至少含Ex) - 每个业务服务启动时,订阅
cache-invalidation频道,收到 key 就清本地缓存或二级缓存 - 避免用
DEL直接删——它不触发 expired 事件,也不通知;要用EXPIRE key 1强制过期来兜底
这种模式下,LRU 参数(maxmemory-policy、maxmemory-samples)只作为内存兜底策略存在,不参与业务逻辑。它的角色是“保命”,不是“同步信号源”。
真正难的是 TTL 精度和 Pub/Sub 的可靠性:过期事件可能延迟几百毫秒,Pub/Sub 消息不保证送达。如果一致性要求高,别只靠这一层,得叠加数据库 binlog 或业务侧双删逻辑。










