前言
主从复制是Redis分布式的基础,Redis的高可用离开了主从复制将无从进行,更是哨兵
和集群
的基石
,非常有必要了解,另外主从复制原理也是面试的常考点,所以我查阅了大量资料,尽可能做到有理有据,图文并茂,以此抛砖引玉,把主从复制原理讲明说透。
一、主从架构
主从架构可以一主一从
,也可以一主多从
,从节点Slave
可以从主节点Master
同步数据,也可以让部分从节点Slave
从从节点Slave
同步数据,缓存主节点压力。
—
二、主从复制全流程
- Slave和Master建立socket长连接
- Slave发psync命令给Master
- Master根据psync参数决定是全量复制,还是部分复制(断点续传)
- 如果全量复制:Master生成rdb,发给Slave加载rdb
- Master发送buffer数据给Slave加载到内存
- 通过socket长连续持续同步写命令数据
三、主从复制细化流程
replicaof 配置
首先,我们需要在Slave
上配置:replicaof [masterIP] [masterPort]
,这个配置代表自己会从masterIP masterPort同步数据。(Redis 5.0之前是slaveof)
redis配置的原文注释说明如下:
slave发psync 命令
只要Slave配置了replicaof,那么不管这个Slave是否是第一次连接上Master,它都会发送一个psync [runId] [offset]
命令给master请求复制数据。(redis2.8之前使用sync,sync只支持全量复制,而psync支持全量和部分复制)
runId
:每个redis节点启动都会生成唯一的uuid,每次redis重启后,runId都会发生变化。客户端执行info server
命令查看:
offset
:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset 命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。
master响应psync 命令
对于Slave发送的psync [runId] [offset]
命令,Master有三种响应:
FULLRESYNC
:进行全量复制
CONTINUE
:进行部分复制 (断点续传)
ERR
:不支持psync命令,进行全量复制
全量复制
全量复制发生的两种情况:
第一次连接
,Slave发送的是psync ? -1
命令,(因为第一次发送,不知道主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。断开重新连接后runid或offset不合法
,Slave会发送存储的master节点runid和已同步的offset,如果master的runid变了,或者slave记录的offset不在master的buffer队列里,那么也会触发全量复制。
详细流程如下图:
补充说明:
- 如果Master收到了多个Slave并发连接请求,它只会进行一次持久化,然后再把这一份持久化的数据发送给多个并发连接的slave。
- Slave如果开启了AOF,在加载RDB后也会异步重写AOF文件。
部分复制(断点续传)
从全量复制中,我们知道Master
有一个缓冲队列repl-backlog-buffer
,这个队列是维护在内存队列中的,缓存固定长度
的数据,是通过repl-backlog-size
配置的,默认1mb
,配置中的注释说明如下:
基于此队列,master和它所有的slave都维护了复制的数据偏移量offset和master的runid,因此,当网络连接断开后,slave通过psync命令发送master的runid和offset,这里master会对比runid是否过期了,或者offset是否维护在缓存队列中,如果满足,从offset开始一次性将数据发送给slave节点。后续仍是通过socket长连接Master持续把写命令发给Slave.
流程图如下:
四、参考资料
面试官:请讲一下Redis主从复制的功能及实现原理 读配置、讲原理、看面试真题,我只能帮你到这了。。 Redis主从复制原理