用户执行SLAVEOF命令或者设置slaveof选项让一个服务器去复制另一个服务器。复制完成后主从服务器保存相同的数据,即主从一致性。
1.1 旧版复制的实现(2.8以前)
复制分为两步:同步和命令传播
- 同步:从服务器发送SYNC命令请求复制,主服务器收到后会执行BGSAVE,生成RDB文件,并在缓冲区记录从现在开始的所有写命令,然后把这些发给从服务器。
- 命令传播:同步完成之后,主服务器进行的写操作会发送给从服务器。
缺陷1:断线重连后要从头开始复制。
缺陷2:SYNC一系列的操作非常耗费资源(CPU、带宽、IO资源)
1.2 新版复制的实现
PSYNC替代SYNC命令,具有完整重同步和部分重同步功能,解决断线重连的问题。
1.2.1 部分重同步的实现
- 主、从服务器的复制偏移量:主从双方维护各自的复制偏移量,断线重连后双方会先确认偏移量是否一样。
- 复制积压缓冲区:由主服务器维护的一个队列,里面保存着最近主服务器传播的一些写命令,从服务器断线期间的数据在缓冲区找,如果没有,才进行完整同步。
- 服务器运行ID:主从服务器都有各自的运行ID(40个随机的16进制字符),从服务器重新上线后要确认此次的主服务器跟上次是否一样,不一样就要进行完整同步。
1.3 心跳检测
在命令传播阶段,从服务器以每秒一次的频率向主服务器发送REPLCONF ACK命令:
- 检测主从服务器连接状态
- 辅助实现min_slave选项:防止主服务器在不安全的情况下执行写命令(从服务器数量少于3,或3个从服务器延迟大于等于10秒,主服务将拒绝执行写命令)
- 检测命令丢失:主服务器向从服务器补发缺失数据(和部分重同步操作原理类似)