Redis 复制 - litter-fish/ReadSource GitHub Wiki
低版本的完全重同步过程:
完全重同步 用于初次同步操作,通过主服务器生成RDB文件,从服务器接收文件后进行还原。
部分重同步 用于断线后重连 实现的组成部分:主从服务器的偏移量、主服务器的复制积压缓冲区、服务器的运行ID,通过这三部分实现部分重同步
-
偏移量 每次主服务器向从服务器传播N字节时,都会将自己复制偏移量的值加上N 从服务器在接收到主服务器传递过来的N字节后,将自己的复制偏移量加上N
-
复制积压缓冲区 是主服务负责维护的一个固定大小的FIFO队列,默认大小1M
当从服务器重新连上主服务器时,会通过PSYNC命令将自己的偏移量发送给主服务器。 主服务器收到命令后会根据偏移量去积压缓冲区中查找: 如果偏移量之后的数据依然存在积压缓冲区中,则主服务器将进行部分重同步 如果偏移量之后的数据已经不存在积压缓冲区中时,则会进行完全重同步。
积压缓冲区大小的调整: 积压缓冲区的最小大小调整规则:second * write_size_pre_second 来估算,second:从服务器断开后重新连上主服务器的平均时间, write_size_pre_second:主服务器平均每秒产生写命令的数量。一般将最小值设置为:2 * second * write_size_pre_second
- 服务器运行ID 当从服务器对主服务进行初次复制时,主服务会将自己的运行ID传给从服务器,从服务器会将这个ID保存起来。 当从服务器重连上主服务器时,从服务器会向当前连接的主服务器发送保存的运行ID: 如果主服务器发现从服务器发送的运行ID与自己ID相等则会尝试进行部分重同步操作, 否则主服务器已经发生了变化,将直接进行全量重同步操作。
PSYNC命令的实现 两种调用方式:
- 从服务器没有复制过任何主服务器,或者之前执行slaveof no one命令,这时从服务器进行第一次新的复制时会发送PSYNC ? -1命令主动进行完全重同步。
- 如果从服务器已经进行过复制,则会通过发送PSYNC 命令,进行同步操作。
主服务器返回的三种情况:
- 如果主服务器发送+FULLRESYNC 命令,表示将进行完全重同步操作,
- 如果返回+CONTINUE,则表示进行部分重同步,从服务器将会等待主服务器发送差异部分
- 如果返回-ERR,表示不支持PYSNC命令,从服务器将发送SYNC命令进行全量重同步。
PSYNC命令的实现步骤
-
客户端向从服务器发送saveof 127.0.0.1 6379命令,从服务器接受到后,保存IP及端口信息,同时向客户端返回OK信息
-
建立套接字,从服务器根据上面的IP和端口建立一个与主服务器的套接字连接 2.1 从服务器关联一个文件处理器,用于接收后面的RDB文件及传播的写命令 2.2 主服务器创建一个客户端状态
-
从服务器发送ping命令,用于检查套接字读写是否正常、检查主服务器是否可以正常处理命令请求。
-
从服务器进行身份验证,从服务器向主服务器发送一条AUTH命令
认证的处理情况:
-
发送端口信息,从服务器执行REPLCONF listening-port ,向主服务器发送从服务器的监听端口。
5.1 主服务器接受到后将端口保存到客户端状态的slave_listening_port中
-
同步,从服务器向主服务器发送PSYN命令
-
命令传播阶段,主服务器将执行的写命令发送给从服务器
在进入传播阶段,从服务器会以每一秒一次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset>
用途:
-
检测主从服务器的网络连接状态,通过向主服务器发送INFO replication命令,可以知道从服务器最后一次发送REPLCONF ACK命令的最后时间
-
辅助实现min-slaves配置 主服务器可以通过,min-slaves-to-write和min-slaves-max-lag两个参数防止主服务器不安全的情况下执行写入操作 min-slaves-to-write N min-slaves-max-lag M 当从服务器的数量少于N,或者N个服务器的延迟值都大于等于M,则主服务器拒绝执行写命令。
-
检测命令丢失 主服务器通过从服务器发送的偏移量可以判断主从同步情况。此种情况与部分重同步的不同时,没有进行断线重连