从节点不执行内存淘汰是设计使然,非配置遗漏:它只同步数据、不参与资源决策,淘汰仅在主节点写命令路径中触发;从节点跳过freememoryifneeded检查,直接应用复制流,故即使maxmemory超限也不淘汰。

从节点不执行内存淘汰是设计使然,不是配置遗漏
Redis 主从架构中,从节点(slave/replica)默认不触发任何 maxmemory 内存淘汰策略,哪怕它的 used_memory 已经超过 maxmemory 配置值。这不是 bug,也不是需要“修复”的行为——它是 Redis 明确规定的语义:**淘汰只发生在写入主节点的上下文中,从节点只负责数据一致性,不参与资源决策**。
为什么从节点跳过淘汰逻辑?关键在 write command 的执行路径
内存淘汰只在写命令(如 SET、HSET、LPUSH 等)执行前触发,而从节点在正常同步状态下,所有写操作都来自主节点的复制流(repl stream),走的是 replicationFeedSlaves 路径,**绕过了主节点上那套完整的命令执行前检查逻辑(包括 freeMemoryIfNeeded)**。
换句话说:从节点收到的不是客户端发来的原始命令,而是已经序列化好的、带时间戳和校验的 RDB 或 AOF 增量数据。它直接 apply 到本地数据库,不做 TTL 检查、也不做内存水位判断。
- 主节点收到
SET key value EX 300→ 先查maxmemory是否超限 → 若超限,按maxmemory-policy淘汰 → 再写入 - 从节点收到该操作的 replication event → 直接写入,不查内存、不触发淘汰
误配从节点 maxmemory 可能导致什么实际问题?
如果你在从节点上也配置了 maxmemory 1G 和 maxmemory-policy allkeys-lru,它不会报错,但会带来两个隐蔽风险:
-
INFO memory中的mem_used会持续上涨,甚至远超主节点 —— 因为过期 key 在从节点上只靠惰性删除(访问时才删),而定期删除的采样频率(hz)在从节点上被降级(默认hz=10,主节点可设更高),导致大量过期 key 积压 - 如果从节点被临时提升为主节点(failover),它会立刻启用淘汰逻辑,但此时内存中可能堆积了大量本该已过期的 key,导致刚切主就触发大规模淘汰,响应延迟飙升
生产环境建议:从节点禁用 maxmemory 或设为 0
除非你明确需要把从节点当读写分离的“热备主”长期使用(且做了容量预估),否则应让从节点内存行为完全跟随主节点节奏:
- 配置中显式设置
maxmemory 0(表示不限制,忽略淘汰) - 或干脆不配置
maxmemory,让其继承默认值 0 - 确保
slave-serve-stale-data yes(允许从节点在断连期间继续提供陈旧数据),避免因内存压力误判服务状态
真正需要关注的是主节点的 evicted_keys 和 expired_keys 监控曲线 —— 从节点的内存水位,只反映同步延迟和 key 生命周期管理是否健康,不该成为淘汰策略的决策依据。











