Redis高可用之主从复制
可以通过SLAVEOF命令或是设置slaveof选项让一个服务器(slave)去复制另一个服务器(master)。
127.0.0.1:12345>SLAVEOF 127.0.0.1 6379
那么 127.0.0.1:12345 就会成为 127.0.0.1:6379 的从服务器。
1、复制功能的原理
复制功能分为同步和命令传播两个操作。
同步是在主从服务器首次建立连接后,从服务器向主服务器发送 SYNC 命令来完成:
(1)从服务器向主服务器发送 SYNC 命令
(2)主服务器收到 SYNC 命令执行 BGSAVE,在后台生成一个 RDB 文件,并使用一个缓冲区来记录从现在开始执行的所有命令
(3)主服务器将生成的 RDB 文件发送给从服务器,从服务器接收 RDB 文件并载入到自己的数据库中
(4)主服务器将记录在缓冲区里的所有写命令发送给从服务器,从服务器执行这些写命令保持与主服务器一致状态
命令传播:同步完成后,主服务器会将自己执行的写命令发送给从服务器,来保持主从状态一致。
1.1、旧版本(2.8以前)复制功能的缺陷
旧版本复制功能的问题是在断线后重复上,旧版的复制在断线重连后,还是以同步的方式向主服务器发送 SYNC 命令,然后主服务器执行 BGSAVE 生成 RDB 文件并发送给从服务器。这就带来两个问题:
(1)主从服务器可能相差很小,但是从服务器还是执行整个 RDB 文件,这样效率是很低的
(2)因为执行 BGSAVE 比较耗性能,如果从服务器频繁断线,会对主服务器造成很大影响
1.2、新版本复制功能的原理
新版复制功能使用 PSYNC,它分为完整同步和部分同步,完整同步和 SYNC 基本一直,也是通过主服务器生成 RDB 文件的方式,用在主从服务器首次建立连接后的同步。部分同步用来处理断线重连后的同步。
部分同步的原理:
部分同步的功能由三部分构成:主从服务器的复制偏移量、主服务器的复制缓冲区、服务器的运行ID(run ID)
(1)复制偏移量
主从服务器分别维护一个复制偏移量,主服务器向从服务器传播 N 个字节数据时,就将自己的复制偏移量加 N,从服务器每次收到主服务器传播来的 N 个字节,也将自己的复制偏移量加 N,这样对比主从服务器的复制偏移量,就能知道两者的同步差距。
(2)复制缓冲区
复制缓冲区是由主服务器维护的一个固定长度的先进先出(FIFO)的队列,默认 1 MB。
当主服务器进行命令传播时,不仅会将写命令发送给从服务器,也会将命令写入到复制缓冲区里。因此复制缓冲区里记录了最近传播的命令,并且复制缓冲区会为每个字节记录相应的复制偏移量。
当主从服务器断线重连之后,从服务器会通过 PSYNC 命令将自己的复制偏移量发送给主服务器,主服务器根据这个复制偏移量来决定后续操作:
? 如果从服务器的复制偏移量之后的数据存在于复制缓冲区里,则对从服务器执行部分不同操作
? 相反,如果不在则对从服务器执行完整同步操作(同老版本的 SYNC 一样通过 RDB 文件的方式)
(3)服务器运行ID
主从服务器都会有运行ID,它是在服务器启动时自动生成的一个40位随机十六进制字符。从服务器初次复制时,主服务器会将自己的运行ID发送给从服务器,从服务器记录下来,在断线重连时将记录的主服务器运行ID发送给主服务器,主服务器以此来判断是首次复制还是断线重连。
2、心跳检测
在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送心跳命令:
REPLCONF ACK offset
offset是从服务器复制偏移量,心跳命令有三个作用:
(1)检测主从服务器网络连接状态
如果主服务器超过一秒没有收到从服务器发送的心跳命令,就知道主从服务器之间的连接出现了问题。
在主服务器执行 INFO replication 命令可以查看从服务器列表。lag 字段就表示从服务器最后一次发送心跳命令的时间(s),一般在0和1之间跳动。
(2)辅助实现 min-slaves 配置选项
Redis提供以下两个配置来保证写命令的安全执行,例如:
min-slaves-to-write 3
min-slaves-max-lag 10
这个配置表示:如果有小于等于3个从服务器的延迟(lag)在10秒以上,则主服务器拒绝写命令。
(3)检测命令丢失
如果因为网络故障等原因导致主服务器传播给从服务器的命令丢失,那么在心跳命令中主服务器根据从服务器发送过来的复制偏移量判断是否存在数据丢失,如果从服务器复制偏移量小于自己的复制偏移量,则将缺失的数据从复制缓冲区里取出一并发送给从服务器。