前面的文章中我们演示过Redis主从配置的操作,可以查看之前的博文Redis主从配置教程。这篇文章主要介绍一下Redis主从复制的工作过程和原理。
Redis复制的工作过程如上图,主要包含以及几个阶段:
SLAVEOF命令执行后从服务器会根据设置的IP和端口向主服务器创建一个socket连接,socket连接通过后从服务器将发送ping命令到主服务器用于判断当前socket连接的读写是否正常。当主服务器回复为pong是则证明连接成功,如果不为pong则会断开重连。
如果从服务器开启了masterauth选项时则需要进行身份的验证,从服务会向主服务器发送一条带有密码的AUTH命令,主服务器接收到AUTH命令发送来的密码并和自己服务器requirepass选项设置的密码进行匹配,如果一致则验证成功。
主服务器身份验证成功后,从服务器会向主服务器发送当前从服务器监听端口号的执行命令 REPLCONF listening-port XXXX,主服务会将端口号记录在它的从服务器客户端配置中。
主从服务器验证完成后,从服务器会向主从服务器发送数据同步的命令,SYNC/PSYNC命令进行数据同步。Redis2.8版本之前时使用SYNC命令,2.8版本之后使用PSYNC命令。下面我们重点会介绍这两种同步的原理。
同步操作执行完后。每当主服务器执行写操作的命令后会将改写操作命令发送给从服务器进行执行,从而达到主从服务器数据一致。
在命令传播阶段,从服务器默认会每秒向主服务器发起心跳检测命令:REPLCONF ACK [从服务器的复制偏移量]。主要作用时检测主从服务器的网络连接状态,辅助实现min-slaves选项。
以上则是Redis主从复制的工作过程。接下去重点介绍一下Redis同步的原理。
Redis同步的动作主要时发生在首次建立主从服务连接和主从服务器断开重连。上文中也提到Redis同步有SYNC同步和PSYNC同步。
在redis2.8版本之前都是SYNC同步。
SYNC同步的主要工作原理:
1.从服务器向主服务器发送sync命令。
2. 主服务器执行bgsave命令,生成rdb文件,并使用一个缓冲区记录从当前开始执行的写命令。
3. 主服务器将rdb文件发送给从服务器,从服务器载入rdb文件。
SYNC同步的缺陷:
每次都需要进行完整的复制,对性能和效率都会有影响。
Redis从2.8版本开始使用PSYNC命令替代了SYNC命令,PSYNC同时具有完整同步和部分同步操作。
实现PSYNC同步功能主要有以下三个部分构成:
1. 主/从服务器的复制偏移量
主从服务器在执行复制时都会维护一个复制偏移量,这个复制偏移量在每次复制时会加上这次复制的数据字节数。复制偏移量的作用判断主从服务器的数据是否一致,同时也通过复制偏移量来获取需要同步的数据。
2. 复制积压缓冲区
由主服务器维护的一个固定长度的队列默认大小时1M,主服务器进行命令传播时。将写命令发送给所有从服务器,并将写命令入队到复制积压缓冲区,积压缓冲区会为每个字节记录相应的复制偏移量。当从服务器发起psync命令时会将自己的复制偏移量发送给主服务器,主服务器会从复制缓冲器进行查找,如果存在则执行部分同步,如果不存在则执行完整同步。
3. 服务器运行ID(runID)
每个redis服务器开启时都会生成唯一的一个运行ID,由40个随机的十六进制字符组成,从服务器在连接上主服务器时会将主服务器的runid保存下来。
它的作用主要是当从服务器断线重连主服务器时从服务器会先判断当前连接的主服务器runid与之前记录的主服务器runID是否一致,不一致则执行完整同步,一致则执行部分同步,第二个作用是在哨兵模式下runID也会成为选举主服务器的一个条件(哨兵模式下会提到)。
PSYNC同步的主要工作原理:
1.客户端发起SLAVEOF命令时,首先判断是否为第一次连接复制如果是则执行完整同步,如果不是则进入下一步。
2. 第二步判断当前从服务器连接的主服务runID与之前记录的是否一致,不一致则证明是新的主服务器则进行完整同步。 如果一致则发送部分同步的命令 把从服务器的runID 和复制偏移量发送给主服务器。
3. 主服务器接收到命令后判断该复制偏移量是否在复制积压缓冲区,如果在则执行部分同步,如果不在则执行完整同步,到此数据同步操作完成。
Redis同步分为SYNC和PSYNC同步,SYNC同步时完整数据同步,PSYNC同步实现了部分数据同步。PSYNC同步主要依靠复制偏移量、复制积压缓冲区、服务器runID来实现。