主从同步

Redis 高可靠性

  • 数据尽量少丢失
    • AOF和RDB保证数据少量丢失
  • 服务经常少中断
    • 增加副本的冗余,将一份数据同时保存在多个实例上

Redis 提供了主从同步模式,保证数据副本的一致,主从库之间采用的是读写分离的方式。

读操作:主库从库都可以接收

写操作: 首先到主库执行,然后主库将写操作同步到从库

Redis主从库和读写分离

为什么要采用读写分离的方式呢?

在三台机器都能操作写数据操作,每次写操作会分到不同的机器上,如果保持数据一致性,就要涉及到加锁、实例之间的协商是否完成修改操作会带开巨额的开销。主从库使用读写分离模式,所有的修改的数据只在主库执行,然后同步到从库,这样就会不用协调三个实例。

主从库数据同步

主从同步关系通过replicaof(Redis 5.0之前使用slaveof)命令关联.

主从库间的同步分三个阶段。

第一阶段

从库和主库建立连接,并告诉主库即将进行同步,主库确认回复后,主从库间就可以开始全量同步。

具体流程

从库给主库发送psync命令(psync命令包含主库runId和复制进度),表示要进行数据同步,主库根据这个命令的参数启动复制。

  • runID: 每个Redis 实例启动都会生成一个随机ID,用来唯一标示这个实例。第一次复制 runID设为”?”,因为不知道主库runID。
  • offset: 第一次复制设为-1

主库收到psync命令后,使用FULLRESYNC命令响应并且带上主库runID和主库目前服复制的进度offset返回从库。从库收到响应会记录两个参数。FULLRESYNC响应表示第一次复制采用的全量复制。

第二阶段

主库将所有的数据同步给从库。从库收到数据,本地完成加载数据。这个过程依赖于内存快照生吃RDB文件。

具体流程

主库执行bgsave命令生成RDB文件,把文件发送给从库。从库收到RDB文件,清空当前数据库(避免已有数据影响当前数据),然后加载RDB文件。

主库将数据同步给从库的过程,主库不会阻塞,继续处理请求。这些新的请求并未记录到刚刚生成RDB文件中。为了主库的数据一致性,主库会在内存中用专门的replication buffer,记录RDB生成后所有写的操作。

第三阶段

主库把第二阶段执行过程中新收到的写命令,再发给从库。

具体操作

主库完成RDB文件发送后,就会把此时replication buffer 中的修改操作发给从库,从库在执行这些操作。

主从级联模式分担全量复制时的主库压力

主从第一次同步时候是全量复制数据,需要操作两个耗时操作:生成RDB文件和传输RDB文件。

从库数量多的时候,会给主库带来压力。可以使用主-从-从模式,使用一个配置比较好的从库来分担主库的压力。这样我个人认为主从从模式会有一定的数据延迟。

主从库网络断了怎么办?

Redis 2.8之前,网络闪断主从库进行一次全量复制,开销非常大。

Redis 2.8以后,网络断了,主从库会采用增量复制的方式同步。增量复制只把网络断连期间收到的命令同步给从库。

repl_backlog_buffer:它是为了从库断开之后,如何找到主从差异数据而设计的环形缓冲区,从而避免全量同步带来的性能开销。

  • 如果从库断开时间太久,repl_backlog_buffer环形缓冲区被主库的写命令覆盖了,那么从库连上主库后只能乖乖地进行一次全量同步,
  • 所以repl_backlog_buffer配置尽量大一些,可以降低主从断开后全量同步的概率。
  • 而在repl_backlog_buffer中找主从差异的数据后,如何发给从库呢?这就用到了replication buffer。

replication buffer:Redis和客户端通信也好,和从库通信也好,

  • Redis都需要给分配一个 内存buffer进行数据交互,客户端是一个client,从库也是一个client,
  • 我们每个client连上Redis后,Redis都会分配一个client buffer,所有数据交互都是通过这个buffer进行的:
    • Redis先把数据写到这个buffer中,
    • 然后再把buffer中的数据发到client socket中再通过网络发送出去,这样就完成了数据交互。
  • 所以主从在增量同步时,从库作为一个client,也会分配一个buffer,
    • 只不过这个buffer专门用来传播用户的写命令到从库,保证主从数据一致,我们通常把它叫做replication buffer。

我们可以调整 repl_backlog_size 这个参数。这个参数和所需的缓冲空间大小有关。缓冲空间的计算公式是:缓冲空间大小 = 主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小。在实际应用中,考虑到可能存在一些突发的请求压力,我们通常需要把这个缓冲空间扩大一倍,即 repl_backlog_size = 缓冲空间大小 * 2,这也就是 repl_backlog_size 的最终值。

主从全量同步使用RDB而不使用AOF?

RDB文件内容是经常压缩的二进制数据,文件很小。而AOF文件是每次操作命令行,文件很大。RDB比AOF数据执行快。