redis主从复制中过期数据由主节点统一删除并发送del命令,从节点不主动判断或清理过期键;主节点通过expireifneeded(惰性)和activeexpirecycle(定期)触发删除,再同步del至从节点执行,以此保障cp一致性。

expireIfNeeded,它只等主节点发 DEL 命令才删**。所以“清理过期数据”这件事,本质是确保主节点能及时触发删除,并让从节点正确响应。
主节点怎么触发过期键删除?
主节点靠 activeExpireCycle 定期扫描 + expireIfNeeded 惰性触发双保险:
-
activeExpireCycle默认每秒执行 10 次(由server.hz控制),每次最多耗时 25ms,随机抽检带过期时间的 key 删除 - 任何读写命令访问 key 时,都会调用
expireIfNeeded:若已过期,主节点先发DEL到 AOF 和所有从节点,再本地删 - 注意:
expireIfNeeded在从节点上也会被调用,但它不会真正删除,只返回-2(TTL 返回值)并跳过删除逻辑
从节点读到过期数据怎么办?
这是最常踩的坑:明明主节点已过期,从节点却仍返回旧值。原因和解法很明确:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- Redis 3.2 之前版本:从节点完全不检查过期,
GET直接返回内存里的值 —— 必须升级到3.2+ - Redis 3.2+ 版本:从节点在读操作时会用自身逻辑时钟判断是否“已过期”,若过期则返回
nil(但不删内存) - 即使返回
nil,该 key 仍留在从节点内存里,直到收到主节点同步来的DEL或下次activeExpireCycle扫描(仅限读写从节点且启用了slave-keys-with-expire) - 网络延迟或主从复制积压会导致
DEL命令滞后 —— 此时只能接受短暂脏读,无法彻底避免
读写从节点时的过期键特殊处理
如果开启了 replica-read-only no(即从节点可写),它自己设的带过期时间的 key 会进 slaveKeysWithExpire 字典,由 expireSlaveKeys 单独清理:
- 这个机制只针对从节点自己写的 key,不处理主节点同步来的 key
-
expireSlaveKeys在每次事件循环中调用,但默认不启用 —— 它只在首次调用rememberSlaveKeyWithExpire后懒创建字典 - 该字典用 bitmap 标记 DB ID,目前只支持 DB 0–63;DB ID >63 的 key 不会被清理
- 如果你依赖从节点写入临时缓存并设 TTL,务必确认 DB ID 范围,并监控
slaveKeysWithExpire字典大小
server.hz 设置过低、大量 key 集中过期……这些都会让过期键在从节点滞留数秒甚至更久。别指望它实时,设计时就得按“最多延迟一个复制周期”来兜底。










