Redis主从-主从数据同步原理

一、前言:主从同步不是"简单拷贝"

很多开发者认为 Redis 主从同步就是"主节点把数据发给从节点",

真正的挑战在于

  • 如何在不停写的情况下完成全量同步?
  • 网络闪断后,如何避免重新全量同步
  • 从节点如何精确追上主节点的最新状态

Redis 通过 PSYNC 协议(Partial Synchronization) 实现了高效、可靠的复制机制。

本文将带你深入源码级实现,揭开主从同步背后的精妙设计。


二、主从同步的核心目标与演进

目标

让从节点(Replica)的数据状态最终与主节点(Master)完全一致,且对主节点性能影响最小。

协议演进

版本 协议 缺陷
Redis 2.8 之前 SYNC 每次断连都全量同步,效率极低
Redis 2.8 ~ 3.x PSYNC1 支持部分重同步,但主节点重启后仍需全量
Redis 4.0+ PSYNC2 支持主节点重启后的部分重同步(终极方案)

本文聚焦 PSYNC2(现代 Redis 默认协议)


三、主从同步全流程(含状态机)

整个过程分为两个阶段:

  1. 全量复制(Full Resynchronization)
  2. 增量复制(Partial Resynchronization)

四、阶段一:全量复制(首次同步 or PSYNC 失败)

触发场景

  • 从节点首次连接主节点
  • 主从断连太久,复制积压缓冲区已覆盖所需数据
  • 主节点重启且未开启 replid 持久化(旧版)

关键设计点

4.1 复制客户端(Replication Client)
  • 主节点为每个从节点创建一个虚拟客户端
  • BGSAVE 开始,所有写命令都会额外发送一份给该客户端
  • 命令暂存在客户端输出缓冲区,待 RDB 发送完成后立即推送

保证全量同步期间的数据不丢失

4.2 复制积压缓冲区(Replication Backlog)
  • 主节点维护一个固定长度的环形缓冲区(默认 1MB)
  • 存储最近执行的写命令(RESP 格式)
  • 用于后续部分重同步

配置项:

复制代码
repl-backlog-size 1mb  # 可根据网络稳定性调整(如 100mb)

五、阶段二:增量复制(PSYNC 成功)

5.1 核心机制:偏移量(offset) + 复制 ID(replid)

  • master_repl_offset:主节点已发送的字节数(全局递增)
  • slave_read_repl_offset:从节点已接收的字节数
  • master_replid:主节点的唯一标识(40 字节十六进制字符串)

📌 只要 replid 相同 + offset 在 backlog 范围内 → 可部分重同步

5.2 PSYNC2 的突破:持久化 replid

Redis 4.0+ 将主节点的 replidrepl_offset 持久化到 RDB 文件末尾

复制代码
RDB 文件结构:
[REDIS][...数据...][EOF][aux: repl-id=abc123][aux: repl-offset=12345]

效果

  • 主节点重启后,从 RDB 中恢复 replidoffset
  • 从节点断连重连时,携带旧 replidoffset
  • 主节点发现 replid 匹配 → 直接从 backlog 补发缺失命令!

彻底解决"主节点重启导致全量同步"的历史难题


六、PSYNC 命令交互详解

6.1 从节点发起同步

bash 复制代码
# 首次连接 or 不知道主状态
PSYNC ? -1

# 断连重连(携带上次的 replid 和 offset)
PSYNC abc123 12345

6.2 主节点响应

响应 含义 后续动作
+FULLRESYNC <replid> <offset> 需全量同步 从节点准备接收 RDB
+CONTINUE 可部分重同步 从节点准备接收增量命令
-ERR ... 协议错误 降级到 SYNC(旧版)

七、关键配置参数与调优

参数 默认值 说明 生产建议
repl-backlog-size 1mb 复制积压缓冲区大小 高延迟网络设为 100~500mb
repl-timeout 60s 复制超时时间 根据网络质量调整
client-output-buffer-limit replica 256mb 从节点输出缓冲区限制 避免大 Key 导致主 OOM
repl-diskless-sync no 是否无盘复制 SSD 环境可开启,减少磁盘 IO

💡 无盘复制(Diskless Replication)

RDB 直接通过 socket 发送给从节点,不落盘,适合高性能 SSD 环境。


八、主从同步的可靠性保障

8.1 心跳机制

  • 从节点每秒发送 REPLCONF ACK <offset> 给主节点
  • 主节点据此更新 slave_ack_offset,用于:
    • 计算从节点延迟(lag = master_offset - slave_ack_offset
    • min-replicas-to-write 安全写入控制

8.2 安全写入(防脑裂)

复制代码
# 至少有 1 个从节点在线且延迟 < 10 秒,才允许写入
min-replicas-to-write 1
min-replicas-max-lag 10

避免主节点网络分区时继续写入导致数据不一致


九、常见问题与排查

❓ Q1:为什么总是全量同步?

  • 原因1repl-backlog-size 太小,断连期间数据被覆盖
  • 原因2:主节点重启(旧版 Redis)
  • 排查INFO replication 查看 master_replid 是否变化

❓ Q2:主从延迟(lag)很高?

  • 可能原因
    • 从节点磁盘慢(加载 RDB 慢)
    • 网络带宽不足
    • 主节点写入突增(大 Key、FLUSHALL)
  • 优化 :增大 repl-backlog-size,升级从节点硬件

❓ Q3:从节点无法写入?

  • 正常现象 :从节点默认 replica-read-only yes
  • 如需写 (如临时调试):CONFIG SET replica-read-only no(重启失效)

十、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
jackiehome4 分钟前
SQL数据库无法操作,日志文件损坏修复
数据库·sql·oracle
我是伪码农12 分钟前
HTML和CSS复习
前端·css·html
林恒smileZAZ13 分钟前
前端实现进度条
前端
前端老石人16 分钟前
邂逅前端开发:从基础到实践的全景指南
开发语言·前端·html
荒川之神19 分钟前
ORACLE导入导出实验
数据库·oracle
执笔为剑22 分钟前
利用逻辑备份修复误操作的库
数据库·kingbase
阿珊和她的猫26 分钟前
以用户为中心的前端性能指标解析
前端·javascript·css
木心术126 分钟前
OpenClaw网页前端开发与优化全流程指南
前端·人工智能
Amumu1213826 分钟前
HTML5的新特性
前端·html·html5
SeSs IZED32 分钟前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx