旧版复制功能
- 客户端向准从机发送
SLAVEOF
命令,使其变成某台机器的从机 - 从机向主机发送SYNC命令
- 主机收到SYNC命令,并执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录此刻之后的所有写命令
- 主机BGSAVE执行完毕,将RDB发送给从机
- 从机接收并载入RDB文件,更新数据
-
旧版命令传播
客户端向主机发送写命令
- 主机执行写命令
- 主机向从机发送写命令
- 从机执行写命令
旧版复制功能的缺陷
旧版设计中,断线重连后,需要重新发送
SYNC
,重新进行全量复制新版同步步骤
从2.8开始,Redis使用PSYNC代替SYNC进行同步。PSYNC具有完整重同步(full resynchronization)、部分重同步(partial resynchronization)两种模式:
完整重同步用于初次同步的情况:操作步骤和SYNC命令一样
部分重同步用于断线后重新复制的情况:从机可以从主机获取断线期间的写命令,并重新执行
部分重同步的实现
重点:
主机和从机的复制偏移量(replication offset)
- 主机的复制积压缓冲区(replication backlog)
-
复制偏移量
主机偏移量:每同步一条命令,就在偏移量上加上这条命令的字节数。同一条命令不重复计数
- 从机偏移量:收到的字节数,每收到一条命令就在偏移量上加上命令的字节数
- 把主机上所有的写命令排成一个字符序列,偏移量其实就是指到这个序列的哪个位置了
偏移量一致,则数据一致。偏移量不一致,从机就应该发送
PSYNC
命令同步数据了复制积压缓冲区
缓冲区实现:固定长度的先进先出队列
- 主机进行命令传播时,把命令发送给从机的同时,还回把命令写入“复制积压缓冲区”
- 当从机断线重连后,主机会根据偏移量来决定使用哪种同步机制
- 从机offset + 1的数据仍在缓冲区中:执行部分重同步的操作
- 从机offset + 1的数据已经不在缓冲区中:执行完整重同步操作
缓冲区大小:默认1MB。高并发写操作时,需要调大缓冲区,避免部分重同步操作机制失效
服务器运行ID
每个redis进程都有自己的运行ID
- 在进程启动时生成,是一个长度40的十六进制字符串
- 根据
ip:port
的方式区分redis进程是不可靠的。如果redis进程在极短的时间内重启了,使用者只根据ip:port
是无法识别出redis的重启行为的 -
PSYNC的具体实现
命令:PSYNC
- 初次同步:PSYNC ? -1
- 再次同步:PSYNC 20549aa994fcd395a1330f05876e552981a5ad12 1536
- 命令回复:
- +FULLRESYNC
:执行完整重同步。offset是指RDB对应的初始offset - +CONTINUE:执行部分重同步。从机接下来等待主机发送写命令就好
- -ERR:主机版本低于2.8从而无法识别命令。从机改为使用SYNC命令进行同步
- +FULLRESYNC
复制的步骤
当客户端向从机发送SLAVEOF命令时:
- 客户端发送:
SLAVEOF 192.168.110.130 6379
- 第一步,记录端口地址:从机将
ip:port
记录到masterhost和masterport中去,然后马上返回OK - 第二步,建立连接:从机主动connect主机
- 第三步,发送PING:connect成功,从机马上发送一个PING请求。
- 如果从机收到错误响应,或者主机响应超时,从机就会断开重连
- 如果从机收到PONG响应,就进行下一个步骤
- 第四步,身份验证:如果从机设置了masterauth选项,从机就会向主机发送一条AUTH命令,没有设置则不发。主机可能有如下响应:
- invalid password:密码错误
- no password is set:主机没有设置密码,但从机发送了AUTH命令
- NOAUTH:主机设置了密码,但从机没有发送AUTH命令
- 通过:两边都没设置密码,或者密码认证通过
- 第五步,发送端口信息:从机执行
REPLCONF listening-port <port>
,向主机发送自己的监听端口号。这个端口号目前只用作INFO命令显示从机信息 - 第六步,同步:从机向主机发送PSYNC命令
-
心跳检测机制
从机每隔一秒向主机发送一次
REPLCONF ACK <replication_offset>
replication_offset 是从机当前的复制偏移量心跳的作用:
min-slaves-max-lag
:最大延迟时间。主机记录了从机最后一次心跳时间,自然也能推算出来是否超过了最大延迟时间。min-slaves-to-write
:最小可写从机个数。对于超过最大延迟时间的从机,就可以认为是不可写的了。防止命令丢失
当写命令丢失时,从机发来的
replication_offset
就会小于主机的复制偏移量。主机这时就会补发缺失的命令- 这个行为和部分重复制有些类似,但是部分重复制是在网络连接断开的情况下,而REPLCONF是在网络连接没有断开的情况下