Redis奇幻之旅(四)2. 主从同步

2. 主从同步

​ Redis可以实现一主N从,为了减少主库的复制压力,还可以做到从从复制。例如:一个主库挂两个从库,两个从库又各自挂了两个从库。

​ 一个slaveof命令即可绑定主从关系,绑定完之后,主库会将从库信息记录在主库redisServer结构体的list *slaves中,从库会将主库信息记录在从库redisServer结构体的char *masterhost和int masterport之中,当然除了列举的这些信息还有其他数据会记录,比如认证信息char *masterauth。(详细可参阅《3.1.2.1 Redis服务启动流程》中的redisServer结构体)

​ 当绑定完成之后,便会进行同步操作。当第一次绑定关系或主从diff过大时,会使用全量同步。反之则使用增量同步。

2.1 全量同步

​ 全量同步大概分三步:

- 从服务器向主服务器发送PSYNC命令

- 主服务器接到PSYNC命令并生成RDB文件(Redis2.8.18开始,这个RDB文件可以通过流传输直接让从服务器生成,这就节省了主服务器的IO操作,称之为“无盘复制”)
- 主服务器将RDB文件发送给从服务器,并且在从服务器在加载完RDB文件之前,会将所有写命令保存在发送缓冲区(大小默认1M),当从服务器完成RDB的载入后,主服务器将成为从服务器的客户端(这里其实是互为客户端)将缓冲区的写命令发送给从服务器。

​ 由于主服务器生成RDB文件需要很多系统资源,所以非必要情况下是不会去执行BGSAVE的,所以全量同步出现在第一次绑定关系或主从diff过大时。

​ 值得注意的是,这里很容易出现的问题是无限全量同步,例如:从服务器接到RDB文件,还未载入完成,而主服务器的发送缓冲区已经超出了1M(缓冲区采用队列,FIFO)。这时从服务器完成载入会发现自己和主服务器的diff过大,然后再执行一次全量同步,如此循环往复。这样会严重影响主服务器对外提供服务的性能,所以为了避免这种情况的出现,我们必须在配置的时候就预估好发送缓冲区的大小。

2.2 增量同步

​ 全量同步中的第三步已经大致说明了增量同步的内容。在从服务器绑定主服务器的时候,我们可以理解成从服务器是主服务器的客户端,而进入增量同步的阶段,主服务器其实也成为了从服务器的客户端,因为主服务器需要将发送缓冲区中的写命令发送给从服务器。

​ 增量同步的功能由三个部分构成:

  • 主从服务器的复制偏移量

  • 主服务器的发送缓冲器(复制积压缓冲区)

  • 服务器的运行ID(这个ID由40个随机的十六进制字符串组成,主要是为了处理从服务器断线后,主服务器刚好也被替换了的问题。)

​ 主服务器每次向从服务器发送N个字节的数据时,就将自己复制偏移量的值加上N,从服务器每次收到主服务器传过来的N个字节的数据时,也会将自己的复制偏移量加上N。可以理解成从服务器一直在追主服务器的偏移量,直到两个偏移量一致。

2.3 心跳检测

​ 主从同步除了同步数据以外还有心跳检测来保证服务及数据的正常,包括:

  • 检测主从服务器的网络连接状态
  • 辅助实现min-slaves选项
  • 检测命令丢失

​ 从服务器会每秒向主服务器发送命令:REPLCONF ACK

​ 在主服务器的INFO replication中,从服务器列表lag里有从服务器向主服务器发送REPLCONF ACK命令距现在的时间,如果超过一秒,则表示连接出现故障。

​ 除此之外,配置文件中有min-slaves-to-write和min-slaves-max-lag两个选项,语义为当存在几个从服务器的连接时长超过lag秒的时候,主服务就拒绝执行写命令,这样来规避主服务器在不安全的情况下执行写命令。

​ 由于增量同步是主服务器给从服务器通过网络发送写命令,但是由于网络的不确定性,所以需要ACK机制来保证从服务器收到了相关数据,所以每次ACK的时候从服务器都会带上自己的偏移量,当主服务器发现从服务器偏移量比自己小的时候,就回再次同步差值的这部分数据给从服务器。

你可能感兴趣的:(Redis奇幻之旅(四)2. 主从同步)