文章目录

  • 前言
  • 一、主从架构
  • 二、主从复制全流程
  • 三、主从复制细化流程
  • replicaof 配置
  • slave发psync 命令
  • master响应psync 命令
  • 全量复制
  • 部分复制(断点续传)
  • 四、参考资料



前言

主从复制是Redis分布式的基础,Redis的高可用离开了主从复制将无从进行,更是哨兵集群基石,非常有必要了解,另外主从复制原理也是面试的常考点,所以我查阅了大量资料,尽可能做到有理有据,图文并茂,以此抛砖引玉,把主从复制原理讲明说透。


一、主从架构

主从架构可以一主一从,也可以一主多从从节点Slave可以从主节点Master同步数据,也可以让部分从节点Slave从节点Slave同步数据,缓存主节点压力。

redis多主多从选举_java


二、主从复制全流程

  1. Slave和Master建立socket长连接
  2. Slave发psync命令给Master
  3. Master根据psync参数决定是全量复制,还是部分复制(断点续传)
  4. 如果全量复制:Master生成rdb,发给Slave加载rdb
  5. Master发送buffer数据给Slave加载到内存
  6. 通过socket长连续持续同步写命令数据

三、主从复制细化流程

replicaof 配置

首先,我们需要在Slave上配置:replicaof [masterIP] [masterPort] ,这个配置代表自己会从masterIP masterPort同步数据。(Redis 5.0之前是slaveof)

redis配置的原文注释说明如下:

redis多主多从选举_主从复制_02

slave发psync 命令

只要Slave配置了replicaof,那么不管这个Slave是否是第一次连接上Master,它都会发送一个psync [runId] [offset]命令给master请求复制数据。(redis2.8之前使用sync,sync只支持全量复制,而psync支持全量和部分复制)

runId:每个redis节点启动都会生成唯一的uuid,每次redis重启后,runId都会发生变化。客户端执行info server 命令查看:

redis多主多从选举_主从复制_03

offset:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。

master响应psync 命令

对于Slave发送的psync [runId] [offset]命令,Master有三种响应:

redis多主多从选举_redis多主多从选举_04

FULLRESYNC:进行全量复制
CONTINUE:进行部分复制 (断点续传)
ERR:不支持psync命令,进行全量复制

全量复制

全量复制发生的两种情况:

  1. 第一次连接,Slave发送的是psync ? -1命令,(因为第一次发送,不知道主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。
  2. 断开重新连接后runid或offset不合法,Slave会发送存储的master节点runid和已同步的offset,如果master的runid变了,或者slave记录的offset不在master的buffer队列里,那么也会触发全量复制。

详细流程如下图:

redis多主多从选举_主从复制_05

补充说明:

  • 如果Master收到了多个Slave并发连接请求,它只会进行一次持久化,然后再把这一份持久化的数据发送给多个并发连接的slave。
  • Slave如果开启了AOF,在加载RDB后也会异步重写AOF文件。

部分复制(断点续传)

从全量复制中,我们知道Master有一个缓冲队列repl-backlog-buffer,这个队列是维护在内存队列中的,缓存固定长度的数据,是通过repl-backlog-size配置的,默认1mb,配置中的注释说明如下:

redis多主多从选举_主从复制_06


基于此队列,master和它所有的slave都维护了复制的数据偏移量offset和master的runid,因此,当网络连接断开后,slave通过psync命令发送master的runid和offset,这里master会对比runid是否过期了,或者offset是否维护在缓存队列中,如果满足,从offset开始一次性将数据发送给slave节点。后续仍是通过socket长连接Master持续把写命令发给Slave.流程图如下:

redis多主多从选举_主从复制_07