在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务去复制另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave)。
复制分为全部复制和部分复制。
1. 主从全部复制
具体步骤为:
- 从服务器跟主服务器建立socket长连接
- 从服务器向主服务器发送PYSNC命令
- 收到PSYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令
- 当主服务器的BGSAVE命令执行完毕后,主服务器就会把BGSAVE命令生成的RDB文件,发送至从服务器,从服务器接到这个RDB文件后,更新自己数据库的状态
- 主服务器将缓冲区里的所有写命令发送至从服务器,从服务器执行这些写命令,更新自己的数据库的状态
上述过程如下图所示:
image
2. 主从部分复制
部分复制功能由以下三个部分构成:
- 主服务器的复制偏移量和从服务器的复制偏移量
- 主服务器的复制积压缓冲区
- 服务器的运行ID
2.1 复制偏移量
执行复制的双方----主服务器和从服务器会分别维护一个复制偏移量:
- 主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N
- 从服务器每次收到主服务器传播来的N个字节的数据时,就将自己的复制偏移量的值加上N
通过对比主从服务器的偏移量,可以很容易的直到主从服务器是否处于一致状态。
2.2 复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度的先进先出队列,默认大小为1MB。
当主服务器进行命令传播时,它不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面,因此,主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。
当从服务器重新连上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作∶
- 如果offset偏移量之后的数据(也即是偏移量 offset+1开始的数据)仍然存在于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作。
- 相反,如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务
器将对从服务器执行完整重同步操作。
2.3 服务器的运行ID
服务器运行在服务器启动时自动生成,由40个随机的十六进制字符组成。
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID 传送给从服务器,而从服务器则会将这个运行ID保存起来。
当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:
- 如果从服务器保存的运行 ID 和当前连接的主服务器的运行ID相同,那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部分重同步操作。
- 相反地,如果从服务器保存的运行 ID 和当前连接的主服务器的运行 ID并不相同,那么说明从服务器断线之前复制的主服务器并不是当前连接的这个主服务器,主服务器将对从服务器执行完整重同步操作。
2.4 部分复制流程
复制流程图如下:
image
3. 复制功能的具体实现
复制的实现步骤:
- 设置主服务器的地址和端口
- 建立套接字连接
- 从服务器向主服务器发送PING命令
- 身份验证
- 向主服务器发送从服务器的监听端口号
- 同步
- 命令传播(写命令)
参考资料
- 《Redis设计与实现》
网友评论