暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

《Redis设计与实现》读书笔记(二十五) ——Redis主从复制具体过程

爱思考的coder 2017-09-12
313

《Redis设计与实现》读书笔记(二十五) 

——Redis主从复制具体过程

(原创内容,转载请注明来源,谢谢)

 


一、PSYNC命令执行过程

         psync是新版redis复制使用的命令,下面讨论其执行过程。

         psync命令调用方法有两种:

         1)从服务器以前如果没有复制过任何主服务器,或者执行过slaveof no one命令,则第一次复制会发送psync ? -1命令,表示强制要求主服务器进行完全重同步。

         2)如果从服务器以前复制过主服务器,则会发送psync <runid> <offset>,将主服务器的运行ID和从服务器当前自身复制偏移量发送给主服务器,由主服务器判断是要部分重同步还是完全重同步。

         主服务器的回复有三种:

         1+fullresync<runid> <offset>,则表示要完全重同步。从服务器会记录runid,作为下次断线重连发送的内容;将offset作为从服务器当前的偏移量。

         2+continue,表示部分重同步,从服务器只需要等待主服务器将缺少的部分发送过来,再进行同步即可。

         3-err,表示主服务器版本低于2.8,不支持psync,则从服务器会再发送sync命令,进行完整同步。

         如下图所示:


、复制的实现

         复制采用的命令是slaveof<masterip> <masterport>,详细实现步骤如下:

1、设置主服务器的ip和端口

         执行上述命令后,从服务器会将主服务器的ip和端口设置在自身redisServer结构体中的属性中,ip设置到char数组的masterhost名称,port设置到intmasterport

         设置完成后,从服务器会向客户端返回OK

2、建立套接字连接

         执行slaveof命令后,从服务器将根据ip和端口号,与主服务器建立套接字连接。

         从服务器成功连接主服务器后,从服务器将为该连接专门创建一个用于复制工作的文件事件处理器,这个处理器接收rdb文件、处理主服务器的命令传播等。

         主服务器接收到从服务器的套接字连接后,为套接字创建相应的状态,并将从服务器看作一个连接到主服务器的客户端,此时从服务器同时具有客户端和服务器两个身份,从服务器可以向主服务器发送命令请求,主服务器会向从服务器发送命令回复。

3、发送PING命令

         从服务器连接上主服务器后,会先发送一个PING命令,具有两个作用:

         1)检查主从服务器的套接字读写状态是否正常。

         2)检查主服务器当前可以正常处理请求。

         从服务器会收到主服务器的三种回复的一种:

         1)主服务器向从服务器回复内容,从服务器不能在规定时限内读取命令内容,则认为主从服务器当前网络不佳,无法处理后续的同步工作。从服务器会断开套接字,再自动重连并重新创建向主服务器的套接字。

         2)主服务器向从服务器回复一个错误,表示主服务器当前无法处理从服务器的请求,从服务器会断开并重新创建向主服务器的套接字。

         3)从服务器接收到主服务器的PONG回复,表示主从服务器网络正常,主服务器当前可以处理从服务器的命令,则从服务器会进入后续的步骤。

         PING命令判断流程如下:

        


4、身份验证

         从服务器收到PONG后,将进入身份验证阶段。

如果其有设置masterauth选项,则开始身份验证,否则不验证。如果需要验证,则从服务器接下来会给主服务器发送auth命令,并带上masterauth选项的值作为参数。

         身份验证阶段会有以下几个结果:

         1)主服务器没有设置requirepass选项,从服务器也没有设置masterauth,则跳过身份验证。

         2)主服务器没有设置requirepass,而从服务器设置masterauth,会报noauth错误。

         3)主服务器设置requirepass,而从服务器没有设置masterauth,会报nopassword is set错误。

         所有错误都会终止当前的复制工作,并从创建套接字开始重新执行复制,直到验证通过。

5、发送端口信息

         身份验证通过后,从服务器会向主服务器发送replconf listening-port <port-number>命令,向从服务器监听端口号。

         主服务器接收到端口号后,会将其记录在对应客户端redisClient结构体中的属性中,类型是int,名称是slave-listening-port。该属性目前唯一作用是主服务器执行info replication命令时,打印出从服务器的端口号。

6、同步

         完成上述步骤后,从服务器会发送psync给主服务器。

在同步操作之前,只有从服务器是主服务器的客户端,而同步之后,主服务器也是从服务器的客户端,即互为客户端。

这样主服务器才可以将保存在缓冲区的写命令(完整重同步)、保存在复制积压缓冲区(部分重同步)中的写命令发给从服务器。

7、命令传播

         完成同步后,后续只要主服务器状态改变,都会给从服务器发送写命令,从服务器执行写命令后,就保证主从一致性。

 

六、心跳检测

         在命令传播阶段,从服务器默认每秒1次的频率,向主服务器发送如下命令:

         replconfack <replication_offset>

         replication_offset是从服务器的偏移量,发送此命令有三个作用:

1、检测主从服务器网络状态。

如果主服务器超过1秒没有接收到从服务器的replconfack命令,表示主从间的连接出问题了。info replication命令可以查看从服务器最后一次发送该命令的时间,属性值是lag,即lag大于1表示出问题了。

2、辅助实现min-slaves选项。

         redismin-slaves-to-writemin-slaves-max-lag两个选项可以在主服务器不安全的情况下,防止执行客户端的写命令。

         例如min-slaves-to-write3min-slaves-max-lag 10,表示少于3个从服务器或三个从服务器的延迟(lag)值都大于等于10秒,主服务器将拒绝执行写命令。

3、检测命令丢失。

         由于每次发送replconfack命令,都带上当前的偏移量,这样就可以保证如果主服务器发送给从服务器的命令传播,由于网络问题导致数据丢失的问题能1秒内被主服务器发现。主服务器发现后,会将相应偏移量的内容从复制积压缓冲区取出,并发送给从服务器。

         replconfack命令和复制积压缓冲区的概念,都是从redis2.8开始有的,在此之前的版本,主服务器无法发现从服务器的数据丢失。因为使用主从的情况下,为了数据一致性,尽量使用2.8以上版本的redis

 

七、总结

         1redis2.8之前的版本,主从复制中,每次从服务器断线重连后,都要进行整个服务器的同步;而2.8版本开始,在一定情况下,可以实现部分重同步。

         2、部分重同步是通过复制偏移量来判断是否需要,通过复制积压缓冲区来取出偏移量范围内的全部数据,通过从服务器发送给主服务器的主服务器运行ID来判断上一次从服务器连接的主服务器与此次连接是否一致。

         3、如果复制偏移量超出复制积压缓冲区,或者从服务器发送的运行ID和主服务器当前运行ID不一致,或者主服务器的redis版本在2.8之前,都会进行完全重同步。

         4、复制刚开始,从服务器是客户端,到开始同步的时候,主从服务器互为客户端。

         5、复制过程包括:从服务器设置主服务器ip和端口;建立套接字;发送PING命令;身份验证;发送端口信息;同步;命令传播。

         6、当主从进入命令传播阶段,从服务器每秒(时间可配置)给主服务器发送一条命令,内容是当前从服务器的偏移量,以确保主从网络正常,并且如果偏移量和主服务器当前的不一致,也便于主服务器再次发送偏移数据,以保证主从数据一致性。

         7、由于效率以及数据一致性,如果要采用主从同步,建议使用redis2.8或以上的版本。



——written by linhxx 2017.09.12

文章转载自爱思考的coder,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论