本文最后更新于 2025-11-07,文章内容可能已经过时。

一、主从同步的分类

Redis主从同步分为两种类型:

  1. 全量同步 (FULL RESYNC):初次同步或数据不一致时进行
  2. 增量同步 (INCREMENTAL RESYNC):后续数据更新时使用

二、全量同步的详细步骤和原理

1. 全量同步触发条件

  • 从节点首次连接主节点
  • 从节点的replid与主节点不一致
  • 从节点请求的offset不在复制积压缓冲区范围内
  • 主节点重启导致replid变化

2. 全量同步流程

步骤1:从节点发起连接

  • 从节点发送PSYNC命令:PSYNC ? -1(首次连接时使用)

步骤2:主节点判断同步类型

  • 主节点检查从节点发送的replid和offset
  • 发现replid不一致(因为从节点是全新的,有自己独立的replid),决定进行全量同步
  • 主节点返回响应:+FULLRESYNC <replid> <offset>

步骤3:主节点生成RDB快照

  • 主节点执行BGSAVE命令,生成RDB快照文件
  • 生成过程中,主节点继续处理写请求,将新写操作记录到repl_baklog(复制积压缓冲区)

步骤4:RDB文件传输

  • 主节点将生成的RDB文件发送给从节点
  • 从节点接收RDB文件并清空本地数据

步骤5:RDB加载

  • 从节点加载RDB文件到内存
  • 从节点保存主节点的replid和offset

步骤6:增量数据同步

  • 主节点将RDB生成期间的命令从repl_baklog中发送给从节点
  • 从节点执行这些命令,使数据与主节点保持一致

步骤7:后续同步

  • 从节点完成初始同步后,主节点持续将新写入的命令发送给从节点
  • 从节点执行这些命令,保持数据同步

三、增量同步的原理

1. 增量同步触发条件

  • 从节点与主节点的replid一致
  • 从节点的offset在主节点的repl_baklog范围内

2. 增量同步流程

步骤1:从节点发送PSYNC命令

  • 从节点发送PSYNC命令:PSYNC <replid> <offset>
  • 其中replid是主节点的replid,offset是当前已同步的偏移量

步骤2:主节点检查同步条件

  • 主节点检查replid是否一致
  • 检查offset是否在repl_baklog范围内
  • 如果条件满足,返回+CONTINUE

步骤3:增量数据传输

  • 主节点将repl_baklog中从offset开始的命令发送给从节点
  • 从节点执行这些命令,更新自己的数据集

步骤4:持续同步

  • 从节点持续接收并执行主节点发送的增量命令
  • 保持与主节点的数据一致

四、关键机制原理

1. 复制ID (replid) 和偏移量 (offset)

  • replid:数据集的唯一标识,每个主节点有唯一的replid
  • offset:同步偏移量,随着记录在repl_baklog中的数据增多而增大
  • 主节点通过比较replid和offset来判断是否需要全量同步

2. 复制积压缓冲区 (repl_baklog)

  • 一个固定大小的环形缓冲区(数组)
  • 记录Redis处理过的命令日志及offset
  • 保存最近一段时间的写操作,用于增量同步
  • 缓冲区大小计算缓冲区大小 = 断线时间 × 写入速度

例如:网络可能断开60秒,写入速度1MB/秒 → 缓冲区大小应为60MB

3. PSYNC命令解析

场景从节点发送命令主节点响应说明
首次连接PSYNC ? -1+FULLRESYNC 需要全量同步
重连PSYNC +CONTINUE可以增量同步
重连PSYNC +FULLRESYNC <new_replid> 需要全量同步

4. 全量同步与增量同步的对比

特性全量同步增量同步
触发条件首次连接、replid不匹配、offset超出范围replid匹配、offset在缓冲区范围内
数据传输RDB文件(可能很大)仅增量命令(较小)
影响主节点fork进程生成RDB,可能造成短暂性能下降仅传输增量命令,影响小
适用场景初始同步、断线时间过长日常同步

五、主从同步的异步性

  • 异步复制:主节点不会等待从节点确认,也不会重传丢失的数据
  • 优点:低延迟、高吞吐量
  • 缺点:数据不一致风险(主节点宕机时,从节点可能丢失部分数据)
  • 数据丢失风险:如果主节点宕机,从节点可能丢失最近的写操作

六、复制积压缓冲区的局限性

  • 缓冲区大小限制:如果网络断开时间过长,导致repl_baklog中的数据被覆盖
  • 无法增量同步:当从节点的offset被覆盖时,无法进行增量同步,必须进行全量同步
  • 解决方案:合理设置repl-backlog-sizerepl-backlog-ttl参数

七、从节点的只读模式

  • 从节点默认是只读的,可配置slave-read-only yes
  • 从节点处理读请求,主节点处理写请求
  • 从节点直接写入会导致数据不一致,因此需要设置为只读

八、主从同步的优化建议

  1. 配置无磁盘复制repl-diskless-sync yes

    • 避免全量同步时的磁盘I/O开销
    • 通过网络直接传输RDB文件,无需生成磁盘文件
  2. 合理设置repl-backlog-size

    • 根据业务场景计算:缓冲区大小 = 断线时间 × 写入速度
    • 例如:网络可能断开300秒,写入速度1MB/秒 → 300MB
  3. 设置repl-backlog-ttl

    • 例如:repl-backlog-ttl 3600(1小时后释放缓冲区)
  4. 监控主从同步延迟

    • 通过INFO replication查看slave_lag(延迟时间)
    • 适当调整配置,保证同步延迟在可接受范围内

九、总结

Redis主从同步的核心原理是通过replid和offset来判断同步类型,使用repl_baklog作为增量同步的缓冲区。全量同步用于初始同步或数据不一致情况,增量同步用于日常数据更新。主从同步是异步的,具有低延迟和高吞吐量的优点,但也存在数据不一致的风险。