redis-复制
在redis中,用户可以通过执行slaveof
命令或者设置slaveof选项,让一个服务器去复制另一个服务器。被复制的服务器为主服务器(master),另一个对主服务器进行复制的服务器称为从服务器(slave)
具体流程
- 从服务器发送
sync
命令到主服务器 - 主服务器通过besave生成rdb文件,发送给从服务器
- 主服务器在bgsave过程中的写操作,保存在缓冲区中,发送给从服务器
进行复制中的主从服务器双方的数据库将保存相同的数据,概念上将这种现象称为数据库状态一致
旧版复制功能的缺陷
旧版指的是2.8之前
在redis中,从服务器对主服务器的复制可以分成两种情况:
- 初次复制:从服务器从前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同
- 断线后重新复制:处于命令转播阶段的主从服务器因为网络原因中断了复制,但从服务器通过自动连接重连上了主服务器,继续复制主服务器
对于初次复制来说,旧版复制完全没有问题,但是断线重连之后,如果当时从服务器已经复制了一些,重连之后,从服务器需要重新复制,造成一些浪费
旧版使用的是sync命令进行复制,是一个非常浪费资源的操作
新版复制的优势
使用psync
命令代替sync命令来执行复制时的同步操作
具有**完整重同步(full resynchronization)和部分重同步(partial resynchronization)**两种模式
- 完整重同步:与初次复制相同,都是先让主服务器发送rdb文件,以及向从服务器发送保存在缓冲区里面的命令来进行同步
- 部分重同步:当服务器断线的时候,下次可以发起psync命令,从中断处开始,执行部分重同步,只需要将从服务器缺少的写命令发送给从服务器执行就可以了,这时使用的资源比起执行sync命令所需的资源要少的多
新版复制实现
部分重同步由以下三个部分构成
-
主服务器的复制偏移量和从服务器的复制偏移量
主从服务器都各自持有一份复制偏移量。如果偏移量一致,表示处于一致状态;否则两者处于不一致状态
-
主服务器的复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个长度固定,先进先出的队列,默认1mb
主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量
当从服务器重新连上主服务器时,从服务器会通过psync命令将自己的偏移量发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作
-
服务器的运行id
每个服务器都有自己的运行id,在服务器启动时自动生成,由40个堆积的十六进制字符组成
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行id传送给从服务器,而从服务器则会将这个运行id保存起来
断线重连后,如果从服务器保存的运行id与当前链接的主服务器运行id相同,主服务器会尝试执行部分重同步操作
相反的,如果不一致,主服务器将对从服务器执行完整重同步操作
心跳检测
在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令
replconf ack <replication_offset>
其中replication_offset是从服务器当前的复制偏移量
发送replconf ack有三个作用:
- 检测主从服务器的网络连接状况
- 辅助实现min-slaves选项
- 检测命令丢失
总结
- 部分重同步通过复制偏移量、复制积压缓冲区、服务器运行id三个部分来实现
- 在复制操作刚开始的时候,从服务器会成为主服务器的客户端,并通过向主服务器发送命令请求来执行复制步骤,而在复制操作的后期,主从服务器互相称为对方的客户端
- 主服务器通过向从服务器传播命令来更新从服务器状态,保持从服务器一致,而从服务器则通过向主服务器发送命令来进行心跳检测,以及生命丢失检测