天天看点

Redis的复制原理

为什么要复制?

无论是使用AOF持久化还是RDB持久化,将数据持久化到硬盘上都是非常有必要的,但是除了进行数据的持久化之外,还必须对持久化后的文件进行备份。最好是备份到不同的服务器上,这样才能避免数据丢失事故的发生。

Redis复制的配置

slaveof host port
可以通过执行slaveof命令或者在redis.conf文件中配置slaveof选项,
让一个服务器去复制(replicate)另一个服务器,被复制的服务器为
主服务器(master),复制的服务器成为从服务器(slave)
假设现在有两台Redis服务器
127.0.0.1 6379和127.0.0.1 6380
在127.0.0.1 6380服务器上执行
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
这样服务器127.0.0.1 6380将成为127.0.0.1 6379的从服务器
进行复制的主从服务器上将保存相同的数据
在主服务器上执行
127.0.0.1:6379> set msg hello
OK
127.0.0.1:6379> get msg
"hello"
在主服务器上可以获取到值,在从服务器上也可以获取到
127.0.0.1:6380> get msg
"hello"
           

Redis复制功能的实现

Redis的复制分为同步和命令传播两个操作

同步:将从服务器的数据库状态更新至主服务器当前所属的数控状态
命令传播:主服务器数据库修改,主从服务器数据库状态不一致,让主从服务器
数据库状态重新回到一致状态
           

同步:

当客户端向服务器发送slaveof命令,要求复制主服务器,从服务器先执行同步操作。注意:从服务器在进行同步的时候,会清除自己的所有数据!原有数据丢失,替换为主服务器发来的数据

sync命令
从服务器对主服务器的同步需要向主服务器发送sync命令。
同步的步骤
1,从服务器向主服务器发送SYNC命令。
2,主服务器收到PSYNC命令会执行BGSAVE命令,在后台创建RDB文件,
并使用一个缓冲区记录从现在开始执行的所有写命令。
3,主服务器会将生成的RDB文件发送给从服务器,从服务器接收并载入RDB文件,
从服务器的所有数据丢失,替换为主服务器发来的RDB文件中的数据。
4,主服务器将缓冲区的写命令发送给从服务器,从服务器执行主服务器发来的写命令
           
Redis的复制原理

命令传播

在同步操作执行完毕之后,主从服务器数据库状态一致,但是这种一致不是一成不变,当主服务器执行客户端发送的写命令,主服务器的数据库状态就会被修改,导致主从服务器状态不一致。这时候主服务器就会进行命令传播,将自己执行的写命令发送给从服务器,从服务器接收并执行主服务器发来的写命令,使得主从服务器数据库状态再次一致。

SYNC命令的缺陷:

当从服务器断开的时候,主服务器在从服务器断开到重新连接的是可能会继续
执行写命令。当从服务器重新连接的时候,向主服务器发送SYNC命令。
再次进行同步操作,使得主从服务器数据库状态再次一致。
但是从服务器需要的仅仅只是在断线到重连这段时间主服务器执行的写命令,
为了弥补这一小部分缺失的数据,确需要主服务重新执行一次SYNC命令,而
SYNC命令是非常消耗资源的操作,这样是很低效的。
           

PSYNC命令:

为了解决断线重连复制的低效问题,Redis从2.8版本开始,使用PSYNC命令来代替SYNC命令来执行复制的同步操作

PSYNC具有完整重同步和部分重同步

完整重同步:和sync命令的同步执行的步骤一致,用于处理初次复制的情况
部分重同步:用来处理断线重连后的复制情况,如果情况允许,当服务器在断线
    后重新连接主服务时,主服务器可以将从服务器断开期间执行的写命令
    发送给从服务器,从服务器只要接收并执行这些写命令,就可以和主服务器
    的数据库一致状态保持。
           

主从服务器执行部分重同步的过程

从服务器重连之后向主服务器发送FSYNC命令
主服务器向从服务器返回+CONTUNUE回复,表示执行部分重同步
从服务器接收+CONTINUE回复,准备执行部分部分重同步
主服务器向从服务器发送从服务器断开期间的执行写命令
从服务器接收并执行主服务器发来的写命令
主从服务器的数据库状态一致
           
Redis的复制原理

部分重同步的实现

部分重同步由三个部分构成
1.主从服务器的复制偏移量(replication offset)
2.主服务器的复制积压缓冲区
3.服务器的运行ID
           

复制偏移量(replication offset)

执行复制的双方-主从服务器都会维护一个复制偏移量

主服务器每次向服务器发送N个字节的数据,就将自己的复制偏移量加N
从服务器每次接收到主服务器发送的N个字节数据,也将自己的复制偏移量加N
通过对比主从服务器的复制偏移量,就能知道主从服务器的数据库状态是
否属于一致的状态。
           

当从服务器重连之后,主服务器如何将从服务器断开期间执行的写命令再补偿给从服务器呢?这就需要复制积压缓冲区

复制积压缓冲区

复制积压缓冲区是主服务器维护的一个固定长度的FIFO队列
当主服务器进行命令传播的时候,不仅会将写命令发送给从服务器,还会将写命令
入队到复制积压缓冲区里面
           
Redis的复制原理

当从服务器连接上服务器时,会通过PSYNC命令将自己的复制偏移量发送给主服务器,主服务器会根据这个复制偏移量来决定是执行完全重同步还是部分重同步。

如果复制偏移量offset+1后的数据还在复制积压缓冲区里面,就执行部分重同步
反之则执行完全重同步
           

服务器运行ID

每个Redis服务器都有自己的运行ID,由40个随机的十六进制字符组成
           

在首次复制的时候,主服务器会将自己的运行ID发送给从服务器,从服务器保存起来。

在断线重连之后,从服务器会向主服务器发送之前保存的运行ID。如果和当前重连的主服务器运行ID相同。则说明断线之前从服务器复制的就是这个主服务器。

继续阅读