以上介绍的主从复制过程,是一个开销非常大,而且比较耗时的操作(主要是同步过程耗时),于是从Redis2.8开始,提供了一种优化机制——部分重同步。我们考虑这样一种情况,假设一台从服务器已经与主服务器完成了同步,进入了命令传播阶段,但是由于某些原因,主从服务器之间的网络连接断开了,从服务器在一段时间后,重新连接上了主服务器。按理来说,从服务器和主服务器断开连接的这段时间,没有同步对主服务器的写操作,此时它们已经不一致了,那么从服务器需要重新执行一次主从复制,这又是一次非常耗时的操作。而Redis2.8之后,提供了一种优化机制,若在上面的情况发生时,如果满足某些条件(具体条件之后叙述),可以不进行一次完整的主从复制,而是只同步断开连接的这段时间里,没有同步的操作,这就是部分重同步。
Redis2.8之后,提供了一个新的指令来实现部分重同步,这个指令就是PSYNC。从2.8开始,实现主从复制使用的就不是SYNC了,而是PSYNC,它可以算是SYNC的升级版本。PSYNC支持两种模式:
完整重同步:如果Redis判断当前从服务器需要与主服务器重新进行一次完整的主从复制,则PSYNC指令将执行与SYNC指令完全一样的操作,上面已经描述过了,这里就不重复叙述了;
部分重同步:若从服务器与主服务器断线重连后,满足某些条件,则不进行完整重同步,而是只同步断线过程中,没有同步的部分;
2.6 部分重同步的实现原理
下面我们就来详细分析一下,部分重同步是如何实现的。部分重同步需要依赖以下三个部分:
服务器的运行id;
主服务器的复制积压缓冲区;
主从服务器的复制偏移量;
(1)服务器的运行 id
每一台服务器都会被分配一个运行id,用来标识服务器的身份。从服务器在与一台主服务器连接后,会记录主服务器的id。从服务器与主服务器断开后,可能会重新连接一台主服务器,但是并不一定就是原来的那一台。当从服务器连接到一台主服务器后,会向主服务器发送自己记录的主服务器id,主服务器判断这是不是自己,如果是,表明从服务器之前连接的就是自己,则有可能可以使用部分重同步机制,否则,将重新进行一次完整同步。
(2)主服务器的复制积压缓冲区
首先,复制积压缓冲区是一个固定长度,先进先出的队列,默认 1MB。主服务器在接收到用户发来的写指令时,不仅仅会将写指令发送给从服务器进行同步,同时还会将这个指令放入到复制积压缓冲区中,目的是在从服务器没有成功接收到的时候能够重传。复制缓冲区的结构大致如下:
可以看到,对于复制积压缓冲区中的每一个字节,都有一个对应的偏移量。如果当前缓冲区已经满了,但是又有新的指令需要放入其中,则会将最先放入其中的指令移除,腾出足够空间后,将新指令放入,也就是LRU算法(最近最久未使用),所以,缓冲区中能够存储的指令是有限的。
(3)主从服务器的复制偏移量
主服务器和从服务器会分别维护自己的复制偏移量,主服务器每发送出一个字节,主服务器偏移量就+1,而从服务器每完成一个字节的同步,从服务器偏移量就+1。
什么情况下会触发部分重同步呢?答案就是:若从服务器与主服务器断开连接,并重新连接到同一个主服务器后,会将自己记录的复制偏移量发送给主服务器,主服务器判断这个偏移量之后的所有字节,是否还在复制缓冲区中,如果在,则表明可以进行部分重同步,将复制缓冲区中,这个偏移量之后的所有字节发送给从服务器;若不完全包含,则表明从服务器需要同步的数据,有一部分无法在缓冲区中找到,此时就需要进行一次完整同步。
2.7 配置从服务器
下面讲一讲如何将一台Redis服务器,配置为从服务器,有两种方式:
(1)配置文件
可以在配置Redis的配置文件中,加入以下配置项:
slaveof 主服务器ip 主服务器端口在配置文件中配置了上面这一行,则当前服务器就是一台从服务器,它启动时,就会尝试区连接上面上面这个配置项指定好的主服务器,并在连接成功后发送PSYNC指令,完成之前介绍的步骤。
(2)指令