主从:SLAVEOF 127.0.0.1 6379 分为同步 与 命令传播两个操作:
简单来说:主要是两个步骤:
1 同步:从服务器-》发送SYNC命令(用于复制功能的内部命令)-》主服务器执行BGSAVE命令,生成RDB文件-》主服务器发送RDB文件-》从服务器载入这个RDB文件-》发送缓存区保存的所有写命令-》从服务器执行这些写命令-》状态一致
2 命令传播:主服务器执行过的命令发送给从服务器,从服务器执行完相同命令后,状态达到一致。
版本对比
旧版的主从(2.8之前):
一旦主从因为网络问题发生断线。重新连接后,主从服务器间将再次进行一次同步操作。效率非常低效。
新版主从:(2.8之后):
1 同步功能基本相同与旧版
新增PSYNC命令,区别在于重新连接后的主从服务器不在进行同步操作,而进行部分重同步,及断开时间段内的写命令传播。步骤如下:
2 从服务器-》发送PSYNC命令-》主服务器回复+CONTINUE,表示执行部分重同步 -》主服务器发送断线期间的写命令 -》从服务器执行这些写命令-》状态一致
细节解析
部分重同步的实现(PSYNC):
1 主服务群的复制偏移量(replication offset),和从服务器的复制偏移量.
1 主服务器与N个从服务器之间都维护一个复制偏移量.主服务器每次向从服务器传播N个字节的数据后,就将自己的复制偏移量的值加上N,
从服务器每次收到主服务器传播来的N个字节后,就将自己的复制偏移量的值也加N.
2 通过对比偏移量的值大小来确定是否需要同步
2 主服务器的复制积压缓存区(replication backlog).
1 是由主服务器维护的一个固定长度(fixed-size),先进先出(FIFO)的队列。
2 当主服务器进行命令传播时,它不仅会将写命令发送给所有服务器,还有将写命令入队到复制积压缓存区里面,并为队列的每个字节记录相应的复制偏移量。
3 当从服务器重新连接上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送主服务器,将产生两种情况:
1 offset之后的数据不在复制缓存区里了,那么主服务器将对从服务器执行完整同步操作
2 如果还在,执行部分同步操作。
4 复制缓存区的大小建议:2 * second(重连一次需要的秒数) * write_size_per_second(主服务器平均每秒产生的写命令数量,既协议格式的写命令的长度总和)
3 服务器的运行ID(run ID)
1 每台redis服务器启动时,不论主从都会有自己的运行ID。
2 当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送到从服务器,从服务器进行保存。
3 当断开重新连接时,从服务器将保存起来的ID发送给主服务器,如果运行的id相同,部分重新同步。不同则完全重新同步。
PSYNC命令的实现:
从服务器接到客户端发来的SLAVEOF命令 -》从服务器判断是否第一次执行复制 -》是:向主服务发送PSYNC ? -1 否: 向主服务器发送 PSYNC <runid> <offset> -》是: +FULLRESYNC <runid> coffset> 执行完整重同步 否:主服务器返回+CONTINUE ? 执行部分同步
复制的实现:
1 设置主服务器的地址和端口 从服务器会将主服务器的ip以及端口保存到redisServer中的masterhost熟悉和mastport属性中
2 建立套接字链接
1 根据命令中主服务器的ip与端口,创建连向主服务器的套接字链接,如果成功链接到主服务器,那么从服务器将为这个套接字关联一个专门用于处理复制文件工作的文件事件处理器。负责执行后续的复制工作:比如接受RDB文件。接受主服务器传播的写命令
2 主服务器接受到从服务器的套接字连接后,为该套接字创建相应的客户端。
3 发送PING命令
1 检测套接字的读写状态是否正常。
2 检查主服务器的状态是否是否可以正常处理命令请求。
3 可能会发生的状况:
1 如果不能在规定的时限内,读取命令回复的内容,表示主从网络连接状态不稳定,不能继续执行复制工作。断开并重新创建套接字
2 主服务器向从服务器返回一个错误,那么表示主服务器暂时没办法处理从服务器的请求,那么从服务器断开并重新创建套接字。
3 收到主服务器的PONG回复,便是正常,开始复制工作
4 身份验证 共有以下情况:
1 主从都没有设置密码,直接通过
2 主从设置密码相同,通过
3 主从设置密码不同。失败,重试。
4 主或者从设置了密码,另一方没有。失败,重试。
5 从服务器将执行命令 REPLCONF listening-port <port>,向主服务器发送从服务器的监听端口,主服务器接收到端口号后,会将端口号设置到对应的redisClinent的slave listening_port属性中
6 同步 (完整同步&部分同步)
1 从服务器向主服务器发送PSYNC命令。执行同步操作。
2 在同步操作执行之前,只有从服务器是主服务器的客户端,但是在执行同步操作之后,主服务器也会成为从服务器的客户端。
1 如果是完整同步,那么主服务器需要成为从服务器的客户端,才能将保存在缓冲区内的写命令发送给从服务器执行。
2 如果是部分同步操作,那么主服务器需要成为从服务器的客户端,才能向从服务器的发送保存在复制挤压混存取的写命令去执行。
3 主从互为对方客户端,那么就可以将主服务器执行的写命令发送给从服务器,从服务器只要一直接受并执行主服务器的写命令,即可保持一致。
心跳检测:
心跳检测:在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset>(当前从服务器的复制偏移量)主要作用:
1 检测主从服务器的网络连接状态:如果主服务器超过一秒没有收到从服务器发来的ack命令,就知道主从之间的连接出现问题了
2 辅助实现min-slaves选项:
1 主服务器设置:min-slaves-to-write 3 min-slaves-max-lag 10
2 如果在从服务器的数量少于三个,或者三个从服务器的延迟值都大于等于10秒时,主服务器将拒绝执行写命令
3 检测命令的丢失
1 如果传播命令过程中,因为网络故障出现主从复制的偏移量不一致,那么当从服务器发送ack命令时,主服务器就会察觉从服务器的偏移量有差距,说明之前的传播过程失败了。
2 主服务器会再次向从服务器传播缺失命令。原理与部分同步一致。