一、前言:为什么增量同步是 Redis 高可用的关键?
在 Redis 主从架构中,全量同步(Full Sync)成本高昂——需生成 RDB、传输 GB 级数据、从节点清库重载。
而增量同步(Partial Resynchronization) 则能在网络闪断后秒级恢复,几乎无感知。
这一切,都依赖于 Redis 的 PSYNC 协议(Partial Synchronization)。
本文将深入剖析:
✅ 增量同步的核心机制
✅ PSYNC2 如何跨越主节点重启
✅ 复制积压缓冲区(Backlog)的工作原理
✅ 生产环境配置与调优建议
二、增量同步 vs 全量同步:本质区别
| 数据载体 | RDB 快照文件 | 命令日志(RESP 格式) |
| 传输量 | 整个数据库(GB 级) | 仅缺失命令(KB~MB 级) |
| 触发条件 | 首次连接 or PSYNC 失败 | replid 匹配 + offset 在 backlog 范围内 |
| 恢复时间 | 秒~分钟级 | 毫秒~秒级 |
| 对主影响 | 高(fork + IO) | 极低(仅内存读取) |
✅ 增量同步是 Redis 主从复制高效、可靠的核心!
三、增量同步的三大基石
3.1 复制 ID(Replication ID, replid)
- 主节点启动时生成一个 40 字节的唯一标识(如 a1b2c3…)
- 从节点首次全量同步后,会记录该 replid
- 作用:标识“数据来源是否一致”
🔑 关键突破(Redis 4.0+):
主节点将 replid 和 offset 持久化到 RDB 文件末尾!
即使主节点重启,也能恢复旧 replid,支持跨重启的增量同步。
3.2 复制偏移量(Replication Offset)
- master_repl_offset:主节点已发送的字节数(全局递增)
- slave_read_repl_offset:从节点已接收的字节数
- 延迟(lag) = master_offset – slave_offset
📌 offset 是“同步进度”的精确标尺
3.3 复制积压缓冲区(Replication Backlog)
- 主节点维护一个固定长度的环形缓冲区(默认 1MB)
- 存储最近执行的写命令(RESP 格式)
- 结构:
char *backlog; // 缓冲区指针
long long backlog_size; // 总大小(如 100MB)
long long offset; // 当前写入位置(全局 offset)
✅ 只要从节点的 offset 在 [first_byte_offset, current_offset] 范围内 → 可增量同步
四、PSYNC 协议交互流程(Redis 4.0+ PSYNC2)
4.1 从节点发起同步请求
# 断连重连时,携带上次记录的 replid 和 offset
PSYNC a1b2c3d4… 123456
4.2 主节点响应逻辑

4.3 成功响应:+CONTINUE
- 主节点从 backlog 中定位 offset 对应位置
- 将后续所有命令流式发送给从节点
- 从节点直接执行,无需清库
✅ 整个过程无 fork、无磁盘 IO、无数据重建!
五、复制积压缓冲区(Backlog)详解
5.1 工作原理(环形缓冲区)
|—-[已覆盖]—-|———-[有效数据]———-|
^ ^ ^
first_byte_offset current_offset (master_repl_offset)
- 当写入超过 backlog_size,覆盖最旧数据
- first_byte_offset = master_repl_offset – backlog_histlen + 1
5.2 关键配置
# 复制积压缓冲区大小(默认 1mb)
repl-backlog-size 100mb
# 是否自动调整(Redis 7+ 支持动态 resize)
# 目前仍需手动配置
💡 如何计算合理大小?
repl-backlog-size > (最大网络中断时间 × 主节点写入吞吐)
例如:
- 最大容忍中断 5 分钟
- 写入速度 10 MB/s
→ repl-backlog-size > 5 × 60 × 10 = 3000 MB
六、心跳与 ACK 机制:保障同步可靠性
6.1 从节点定期上报 offset
- 每秒发送:REPLCONF ACK <current_offset>
- 主节点据此更新:slave_ack_offset
6.2 主节点用途
- 计算从节点延迟:lag = master_repl_offset – slave_ack_offset
- 实现安全写入:
min-replicas-to-write 1 # 至少 1 个从在线
min-replicas-max-lag 10 # 延迟 < 10 秒
✅ 避免主节点在网络分区时继续写入(防脑裂)
七、生产环境最佳实践
✅ 配置建议
# 增大 backlog(根据网络稳定性)
repl-backlog-size 500mb
# 启用心跳(默认开启)
repl-ping-replica-period 5
# 设置超时
repl-timeout 60
# 安全写入(可选)
min-replicas-to-write 1
min-replicas-max-lag 10
✅ 监控指标(必看!)
| 主从延迟 | INFO replication → lag | > 30 秒 |
| backlog 使用率 | repl_backlog_histlen / repl_backlog_size | > 90% |
| PSYNC 失败次数 | 日志 grep "Partial resynchronization not accepted" | > 0 |
✅ 故障排查
- 问题:总是全量同步
排查:INFO replication 查看 master_replid 是否变化 - 问题:增量同步后数据不一致
排查:检查是否有 FLUSHALL、DEBUG 等危险命令
八、增量同步的局限性
| 主节点 crash + 未持久化 replid | Redis < 4.0 会生成新 replid | 升级到 Redis 4.0+ |
| 从节点 offset 被 backlog 覆盖 | 网络中断太久 | 增大 repl-backlog-size |
| 主节点执行 SCRIPT FLUSH | 清空 Lua 脚本缓存 | 避免随意刷新脚本 |
⚠️ 注意:KEYS *、FLUSHDB 等大命令会瞬间填满 backlog!
九、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!


