redis没有像mysql那样复制位置的概念,所以Slave和Master断开连接再重新连接时,会全量取Master的快照,Slave的所有数据都会清除,重新建立整个内存表,这样导致Salve恢复数据特别慢,同时也给Master带来的压力。

Redis的主从复制策略是通过其持久化的rdb文件来实现的,其过程是先dump出rdb文件,将rdb文件全量传输给slave,然后再将dump后的操作实时同步到slave中。让从服务器(slave server)成为主服务器(master server)的精确复制品。官方文档ReplicationHowto中提到以下特点:

一个master支持多个slave,slave可以接受其他slave的连接,作为其他slave的master,从而形成一个master-slave的多级结构复制功能不会阻塞主服务器: 即使有一个或多个从服务器正在进行初次同步, 主服务器也可以继续处理命令请求。复制功能不会阻塞从服务器: 只要在 redis.conf 文件中进行了相应的设置, 即使从服务器正在进行初次同步, 服务器也可以使用旧版本的数据集来处理命令查询。不过, 在从服务器删除旧版本数据集并载入新版本数据集的那段时间内, 连接请求会被阻塞。复制被利用来提供可扩展性,比如可以将slave端用作数据冗余,也可以将耗时的命令(比如sort)发往某些slave从而避免master的阻塞,另外也可以用slave做持久化,由从服务器去执行持久化操作,这只需要将master的配置文件中的save指令注释掉。

Redis 使用异步复制。

主从数据同步分为两种同步情况,分为完整重同步部分重同步两种。

完整重同步流程

完整重同步是指:在从服务器第一次启动时,其内部没有任何数据的时候,通过向从服务器发送 slaveof master_ip port 命令,通知从服务器向指定的主服务器发起完整的数据备份请求。具体流程如下:

  1. 客户端向从服务器发送数据同步请求,从服务器接收到命令后,便通过指定的主服务器 ip 和 port 向主服务器发送 PSYNC 请求数据同步。
  2. 主服务器接收到 PSYNC 后,判断是要求进行全量数据同步,此时主服务器生成当前服务器对应的 RDB 文件,然后将其返回给从服务器。
  3. 在从服务器进行数据完整重同步的过程中,主服务器接收到的写请求在自己的服务器中完成命令操作之后,同时将写命令也发送到从服务器中。
  4. 从服务器接收到 RDB 文件后,开始解析 RDB 文件,对 RDB 文件解析完成和主服务器写命令的操作之后,也就意味着数据完成完整重同步流程。

redis集群主从数据同步原理分析 - 图1

以上整个流程便是数据完整重同步的具体执行流程,额外需要注意的一点是,完整重同步其实就是将主服务器的整个完整数据进行一次完整的备份。

部分重同步

部分重同步是指:从服务器在复制了一部分数据后发生了断线重连后继续复制的情形。在从服务器由于网络等原因导致数据同步终止,当网络恢复后,从服务器继续向主服务器进行数据同步操作。Redis 通过偏移量的机制来实现数据部分重同步操作,即主服务器和从服务器都维护着一个执行命令的偏移量,同时在主服务器内部维护着一个复制积压缓冲区(复制积压缓冲区是可以调节大小的,默认大小 1M,通过修改 repl-backlog-size 配置进行修改),该缓冲区中缓存着部分写命令和写命令对应的偏移量。当从服务器断线重连后,从服务器在发送数据同步请求的时候会带着从服务器当前同步的偏移量,如果从服务器发送的偏移量在复制积压缓冲区中存在,则从复制积压缓冲区中对应的偏移量位置继续复制往后位置的命令,如果从服务器发送的偏移量和主服务器维护的偏移量相等,则表示主从数据是一致的。部分重同步流程如下图所示: redis集群主从数据同步原理分析 - 图2

部分重同步机制的优势:

  1. 相比于全量重同步,减少了数据同步量
  2. 由于部分重同步数据量小,可以更快速的达到主从数据一致的目的
  3. 由于数据同步量少,从而节省了带宽资源,同时也节省了主服务器生成 RDB 文件而产生的 CPU 浪费情况