PSYNC请求被主节点拒绝为FULLRESYNC,是因为replid不匹配或offset不在repl-backlog有效区间内;主节点仅当replid完全一致、offset≥repl_backlog_first_byte_offset且≤master_repl_offset时才执行增量同步,任一条件不满足即强制全量。

从节点重连后总是全量同步,大概率是 replid 不匹配或 offset 已失效,而不是网络抖动或配置写错。
为什么PSYNC请求被主节点拒绝为FULLRESYNC?
从节点重连时发送 PSYNC <replid> <offset>,主节点只在同时满足以下三个条件时才走增量同步:
-
replid与主节点当前run_id完全一致(大小写敏感、40位字符串) -
offset≥ 主节点repl_backlog_first_byte_offset -
offset≤ 主节点当前master_repl_offset
任意一条不成立,主节点就直接返回 FULLRESYNC。常见但容易被忽略的是:从节点保存的 replid 是上次连接时主节点给的,如果主节点重启过、发生过故障转移、或被手动 DEBUG RELOAD,run_id 就会变——此时哪怕 offset 还在缓冲区范围内,也必然全量。
怎么快速验证replid是否已变更?
在从节点上执行:
redis-cli INFO replication | grep -E "master_replid|slave_replid"
再在主节点上执行:
redis-cli INFO server | grep run_id
对比两处值:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 若从节点的
slave_replid≠ 主节点的run_id→ 确认replid失配,必须全量 - 若相等,再查主节点的
repl_backlog_first_byte_offset和master_repl_offset,看slave_repl_offset是否落在区间内
注意:slave_replid 字段在从节点 INFO 输出中只在成功建立复制关系后才存在;首次连接或刚执行 REPLICAOF NO ONE 后为空,此时也会退化为全量。
offset看起来“还在范围内”,为什么还是全量?
这是最隐蔽的问题——offset 数值本身没超,但主节点的复制积压缓冲区(repl_backlog)可能根本没启用,或已被清空:
- 检查主节点
repl_backlog_active是否为1(不是所有 Redis 版本默认开启) - 若
repl_backlog_size为0或极小(如默认 1MB),而写入峰值高、断连时间稍长,缓冲区早已循环覆盖 - 主节点执行过
CONFIG RESETSTAT,会重置repl_backlog_first_byte_offset,导致旧offset瞬间“跳到未来”
不要只看差值 master_repl_offset - slave_repl_offset,要严格比对 slave_repl_offset < repl_backlog_first_byte_offset ——这个判断才是主节点内部实际做的逻辑。
哪些操作会静默重置replid或清空backlog?
这些行为不会报错,但会让从节点下次重连必然全量:
- 主节点执行
DEBUG RELOAD(开发测试常用,生产禁用) - 主节点配置了
replica-announce-ip但 DNS 解析失败,部分版本会触发run_id重生成 - 主节点内存不足,
bgsavefork 失败后 fallback 到 diskless sync,过程中可能丢弃 backlog 上下文 - 使用
redis-cli --rdb手动导出 RDB 后又加载,相当于一次“软重启”
真正难排查的,往往不是参数设小了,而是某次看似无关的操作,悄悄改写了复制元数据的连续性。

















