Redis主从复制
Redis主从复制
Hbzhtd前言
学习了《Redis设计与实现》第15章关于主从复制的知识,写篇笔记用于复习吧。
1. 旧版复制功能的实现
在Redis中,用户可以通过 SLAVEOF 命令或者设置 SLAVEOF 选项,让服务器成为主服务器的从服务器。
127.0.0.1:12345> SLAVEOF 127.0.0.1 6379 |
主从数据库保持相同的数据,称之为“数据库状态一致”,简称“一致”。
旧版复制功能的实现分为两种:同步和命令传播。
同步
当客户端执行 SLAVEOF 命令后,从服务器会向主服务器复制数据,通过发送命令 SYNC 完成。执行步骤如下:
- 从服务器向主服务器发送 SYNC 命令。
- 收到 SYNC 命令的主服务器执行 BGSAVE 命令生成 RDB 文件,并使用一个缓冲区用来记录执行 BGSAVE 命令期间所有写命令。
- 当主服务器 BGSAVE 命令执行完毕,主服务器向从服务器发送 RDB 文件,从服务器将 RDB 载入数据库。
- 主服务器将缓冲区中的命令发送给从服务器,从服务器执行命令。
命令传播
当主从数据库达到一致之后,每当主服务器执行一条写命令之后,会将该条命令传播发送给从服务器,达成新的一致性。
2. 旧版复制功能的缺陷
在Redis中,主从复制分为两种:初次复制和断线后重复制。
初次复制是指:从服务器之前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同。
断线后重复制是指:主从服务器在主服务器进行命令传播时,从服务器发生了断线,但从服务器通过重连继续复制主服务器。
对于初次复制没有什么问题,但是断线后重复制性能比较低下。因为每次从服务器断线重连,都会向主服务器发送SYNC命令进行同步操作,会复制主服务器的全量数据,这就导致从服务器之前已经同步过的数据全部无用。
3. 新版复制功能的实现
从Redis 2.8版本开始,使用PSYNC命令来替代SYNC命令。PSYNC 命令具有完整重同步和部分重同步两种模式:
- 完整重同步用于初次复制,等同于SYNC命令。
- 部分重同步用于断线后重复制,当从服务器断线重连后,如果条件允许,主服务器会将从服务器断线重连期间的写命令发送给从服务器,从服务器只需要执行这些写命令就可以达成数据库一致。
4. 部分重同步的实现
首先是实现的细节,部分重同步由三个部分组成:主从服务器的复制偏移量(replication offset)、主服务器的积压缓冲区(replication backlog)、服务器的运行ID。
复制偏移量
执行复制的主从服务器双方,都会维护一个复制偏移量。
- 主服务器每次向从服务器同步N个字节的数据,主服务器的复制偏移量的值就会加上N。
- 从服务器每次从主服务器接收到N个字节的数据,从服务器的复制偏移量的值就会加上N。
举例:假设主服务器此时偏移量为10086,当从服务器执行初次复制后,从服务器的复制偏移量也等于10086。当主服务器进行命令传播时,假设主服务器的复制偏移量为10100,并且从服务器此时断线了,重连后,从服务器偏移量还是10086,这时会向主服务器发送PSYNC命令,并带上从服务器的复制偏移量。主服务器收到后,就会执行部分重同步。
复制积压缓冲区
部分重同步依赖于积压缓冲区,积压缓冲区是由主服务器维护的一个固定长度的队列,默认大小为1MB。
当主服务器进行命令传播时,不仅会将写命令发送给从服务器,还会将写命令写入积压缓冲区。因此积压缓冲区会存储最新的1MB的写命令,并且会给每个字节一个复制偏移量。
当从服务器断线重连发送PSYNC命令后,主服务器根据从服务器发送的复制偏移量,决定执行何种同步模式:
- 如果offset存在于复制积压缓冲区,则执行部分重同步
- 否则执行完整重同步
回到之前的例子,由于从服务器断线重连后,offset为10086,主服务器的offset为10100。当主服务器收到从服务器的PSYNC命令后,发现从服务器的offset小于自身offset,则查看积压缓冲区。如果10086存在于缓冲区,则主服务器将积压缓冲区10087~10100号字节的数据发送给从服务器,达成数据一致。
服务器运行ID
每个Redis服务器,都有自己的服务器ID,在启动时自动生成,由40个十六进制字符组成。当从服务器进行初次复制时,主服务器会将自己的运行ID发给从服务器,从服务器会保存主服务器的运行ID。
当从服务器断线重连后,会向当前连接的主服务器发送上一次保存的运行ID:
- 如果从服务器保存的运行ID和当前连接的主服务器运行ID相等,则尝试执行部分重同步。
- 否则直接执行完整重同步。
5. PSYNC 命令的实现
6. 心跳检测
在命令传播阶段,从服务器向主服务器每秒发送一次命令:REPLCONF ACK
主要有三个作用:
- 检测主从服务器的网络状态
- 辅助实现min-slaves选项
- 检测命令丢失
命令丢失:当主服务器进行命令传播时,命令可能由于网络原因丢失,那么当从服务器执行 REPLCONF ACK命令时,主服务器就能发现从服务器的偏移量小于自身,那么就会从积压缓冲区中发送对应的字节数据。