经过SLAVEOF命令或者设置slaveof选项,让一个服务器(从服务器)去复制另外一个服务器(主服务器),达到“数据库状态一致”效果。redis
同步(sync)数据库
命令传播(command propagate)安全
同步后主服务器数据库被修改,为了让主从服务器保持一致状态,主服务器将本身执行的写命令发送给从服务器执行相同的写命令。服务器
复制可分为初次复制和断线后重复制网络
断线后重复制每次都须要执行一次SYNC命令,从新复制全部的数据库数据,很是低效。ui
区别线程
Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步问题。3d
PSYNC命令具备完整重同步和部分重同步两种模式blog
完整重同步队列
用于处理初次复制状况,和SYNC初次复制基本一致。
部分重同步
用于处理断线后重复制状况,从服务器断线重连后,在必定条件下,主服务器能够将断开期间执行的写命令发送给从服务器。
部分重同步功能由如下三个部分构成:
1. 复制偏移量
主服务器每次向从服务器传播N个字节数据,就将本身的复制偏移量的值加上N;
从服务器每次接收主服务器传播来的N个字节数据,就将本身的复制偏移量的值加N。
经过对比主从服务器的偏移量就能够判断主从服务器是否处于一致状态
2. 复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度(fixed_size)先进先出(FIFO)队列,默认大小为1MB。
主服务器在进行命令传播时,不只会将写命令发送给从服务器,还会将写命令入队到复制积压缓冲区,复制积压缓冲区会为队列中的每一个字节记录相应的复制偏移量。
从服务器断开重连后会经过PSYNC命令将本身的复制偏移量offset发送给主服务器,主服务器根据这个复制偏移量决定执行何种同步操做。
offset偏移量以后的数据仍存在于复制积压缓冲区,则执行部分重同步;
offset偏移量以后的数据不存在于复制积压缓冲区,则执行完整重同步。
复制积压缓冲区的大小能够根据公式second * write_size_per_second来估算
secoond为从服务器断线重连所需的平均时间(以秒计算)
write_size_per_second为主服务器平均每秒产生的写命令数据量
通常修改配置文件中repl-backlog-size选项将复制积压缓冲区大小设为
2 * second * write_size_per_second
3. 服务器运行ID
每一个Redis服务器有本身的运行ID,运行ID在服务器启动时自动生成,由40个随机的十六进制字符组成。
从服务器对主服务器进行初次复制时,主服务器会将本身的运行ID传送给从服务器,从服务器会将这个运行ID保存起来。
当从服务器断线重连上一个主服务器时,从服务器会向当前链接的主服务器发送以前保存的运行ID。
从服务器:
若是从服务器没有复制过任何主服务器或者执行过SLAVEOF no one命 令,则从服务器向主服务器发送PSYNC ? -1命令。请求完整重同步。
若是从服务器复制过某个主服务器,则从服务器向主服务器发送
PSYNC <runid> <offset>命令,主服务器根据两个参数判断执行哪一种同步操做。
主服务器:
经过SLAVEOF <master_ip> <master_port>,设置主从服务器
从服务器将主服务器的IP地址及端口保存到服务器状态的masterhost属性和masterport属性。
从服务器根据命令中的IP地址和端口,建立连向主服务器的套接字链接
若是成功链接,从服务器为该套接字关联一个专门用于处理复制工做的文件事件处理器,如接受RDB文件,接受主服务器传来的写命令等。
若是接受链接,主服务器为该套接字建立相应的客户端状态,这时候从服务器同时具备服务器和客户端两个身份。
从服务器成为主服务器的客户端以后,第一件事就是发送一个PING命令。
PING命令的做用:
- 检查套接字的读写状态是否正常
- 检查主服务器可否正常处理命令请求,为后续步骤作检查
PING命令返回状况:
主服务器返回了一个命令回复,但从服务器不能在规定时限(timeout)内读取出命令回复内容,表示主从服务器之间的网络链接状态不佳,没法继续执行后续步骤。
(从服务器断开并从新建立连向主服务器的套接字)
主服务器返回了一个错误,表示主服务器暂时无法处理从服务器的命令请求,没法继续执行后续步骤。
(从服务器断开并从新建立连向主服务器的套接字)
从服务器读取到“pong”回复,表示主从服务器之间的网络链接状态正常,主服务器能正常处理命令请求,能够继续执行后续步骤。
根据从服务器是否设置了masterauth选项,决定是否进行身份验证。
设置了masterauth:
从服务器向主服务器发送一条AUTH命令,命令参数为从服务器masterauth选项的值
身份验证的三种状况:
主服务器没有设置requirepass选项,从服务器也没有设置masterauth选项,主服务器继续执行从服务器发送的命令,复制工做继续进行。
从服务器经过AUTH命令发送的密码和主服务器requirepass选项设置的密码相同,主服务器继续执行从服务器发送的命令,复制工做继续进行。若是不相同,主服务器返回一个invalid password错误。
若是主服务器设置了requirepass选项,从服务器没有设置masterauth选项,主服务器返回一个NOAUTH错误;
若是主服务器没有设置requirepass选项,从服务器设置了masterauth选项,主服务器返回一个no password is set错误。
从服务器执行命令REPLCONF listening-port <port-number>,向主服务器发送从服务器的监听端口号。
主服务器将端口号记录在从服务器对应的客户端状态的slave_listening_port属性中,该属性目前惟一的做用是在主服务器执行INFO replication命令时打印从服务器的端口号。
从服务器向主服务器发送PSYNC命令,执行同步操做
执行同步操做前,只有从服务器是主服务器的客户端,执行同步操做后,主从服务器互为对方的客户端
(只有成为客户端,才能够互相向对方发送命令请求或者返回命令回复)
主服务器一直将执行的写命令发送给从服务器,从服务器一直接收并执行主服务器发来的写命令,保持主从一致。
命令传播阶段,从服务器每秒一次向主服务器发送命令:
REPLCONF ACK <replication_offset>,其中replication_offset为从服务器当前的复制偏移量。
REPLCONF ACK命令的做用
主服务器超过一秒钟没有收到从服务器发来的REPLCONF ACK命令,则说明主从服务器之间的链接出现问题。
能够经过INFO replication命令,在服务器列表的lag属性查看从服务器上一次发送REPLCONF ACK距离如今的时间。(通常在0~1秒之间跳动)
Redis中的min-slaves-to-write和min-slaves-max-lag能够防止主服务器在不安全的状况下执行写命令,这里的min-slaves-max-lag就是上面提到的读取的lag值。
从服务器在发送REPLCONF ACK命令时发送复制偏移量,若是由于网络故障发生命令丢失,主从服务器复制偏移量不一样,主服务器会根据从服务器提交的复制偏移量,在复制积压缓冲区找到丢失的数据从新发送。
(不一样于部分重同步,区别是有没有断线)