主从复制

目录


为了避免单点故障,多个服务器保存同一份数据,这样即使有一台服务器出现了故障,其他服务器依然可以继续提供服务。

Redis 提供了​​主从复制模式​​​来实现,该模式保证了多台服务器的数据一致性,主从服务器之间采用的是 ​​读写分离​​的方式。

也就是说,所有的数据修改只在主服务器上进行,然后将最新的数据同步给从服务器,这样就使得主从服务器的数据是一致的。


第一次同步

我们可以使用​​replicaof​​(Redis 5.0之前使用slaveof)命令形成主服务器和从服务器的关系。

主从服务器的第一次同步的过程可分为三个阶段,如图:

【Redis】主从复制_操作命令


  1. 执行​​replicaof​​命令后,从服务器就会给主服务器发送​​psync​​命令,表示进行同步。​​psync​​命令包含两个参数,分别是主服务器的​​runlD​​和复制进度​​offset​​。

    • ​runID​​,每个 Redis 服务器在启动时都会自动生产一个随机的 ID 来唯一标识自己。当从服务器和主服务器第一次同步时,因为不知道主服务器的 run ID,所以将其设置为 "?"。
    • ​offset​​,表示复制的进度,第一次同步时,其值为 -1。

  2. 主服务器用 ​​FULLRESYNC​​ 作为响应命令返回给对方,并且会带上两个参数,主服务器的 runID 和主服务器目前的复制进度 offset。
    ​FULLRESYNC ​​响应命令的意图是采用 全量复制 的方式,就是主服务器会把所有的数据都同步给从服务器。
  3. 接着,主服务器会执行​​bgsave​​命令来生成RDB文件,然后把文件发送给从服务器。从服务器收到​​RDB​​文件后,会先清空当前的数据,然后载入​​RDB​​文件。
    在生成​​RDB​​的这个过程不会阻塞主线程,在这期间的写操作命令会写到​​replication buffer​​缓冲区里。
  4. 在生成的​​RDB​​文件发送后,将​​replication buffer​​缓冲区里记录的写操作命令发送给从服务器,然后执行这些操作


基于长连接的命令传播

主从服务器在完成第一次同步后,双方会维护一个TCP 链接来保证主从服务器的数据一致性

后续主服务器可以通过这个连接将写操作命令传播给从服务器,然后从服务器执行该命令,使得与主服务器的数据库状态相同。

而且这个连接是长连接,目的是避免频繁的TCP连接和断开带来的性能开销。


增量复制

从服务器对主服务器的复制可以分为两种情况:


  • 初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同。
  • 断线后重复制:在Redis 2.8 之前,处于命令传播阶段的主从服务器因为网络原因而中断了命令同步,但又重连上了,从服务器会和主服务器重新进行一次全量复制,但是这样效率非常低。

所以在Redis 2.8 开始,全量复制用于初次复制的情况。网络断开又恢复后,主从服务器会采用 增量复制 的方式继续同步,也就是只会把网络断开期间主服务器接收到的写操作命令,同步给从服务器。

主要步骤:


  1. 从服务器恢复网络后,发送​​psync​​​命令,此时​​offset​​参数不是-1;
  2. 主服务器收掉命令后,用​​CONTINUE​​响应命令告诉从服务器接下来采用增量复制的方式同步数据;
  3. 然后主服务将主从服务器断线期间,所执行的写命令发送给从服务器,然后从服务器执行这些命令。

那么主服务器怎么知道要将哪些增量数据发送给从服务器呢?

原因是有这两个东西:复制偏移量(replication offset) 和 复制积压缓冲区(repl_backlog_buffer) .


  • 复制偏移量:执行复制的主服务器和从服务器分别会维护一个复制偏移量,用来标记各自写或读取到的位置。如果两者偏移量不同,说明主从服务器并未处于一致状态。
  • 复制积压缓冲区:由主服务器维护的一个环形缓冲区,默认大小为1M,。在进行命令传播时,不仅会把写命令发送给从服务器,还会将写命令写到积压缓冲区中。当缓冲区写满后,主服务器继续写入的话,就会覆盖之前的数据。

在从服务器重新连上主服务器时,从服务器会通过​​psync​​​命令将自己的复制偏移量​​offset​​发送给主服务器:


  • 如果​​offset​​偏移后的数据仍然存在于复制积压缓冲区中,那么就执行增量复制的同步操作。
  • 相反执行全量复制。

所以如果复制积压缓冲区配置的过小,主从服务器网络恢复时,可能发生「从服务器」想读的数据已经被覆盖了,那么这时就会导致主服务器采用全量复制的方式。所以为了避免这种情况的频繁发生,要调大这个参数的值,以降低主从服务器断开后全量同步的概率。


心跳检测

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

REPLCONF ACK <replication_offset> 

​replication_offset​​是从服务器当前的复制偏移量。

主要有三个作用:


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