Redis主从复制与一致性

2021-11-12  本文已影响0人  爱钓鱼的码农

复制简介

数据的同步过程一般都涉及到全量数据的迁移以及后续增量数据的同步。

SYNC同步

在主Master接收到SYNC命令之后,它会执行bgsave在后台生成一个RDB文件,并且使用一个缓冲区记录从现在开始执行所有写命令。当bgsave生成的RDB文件完成了之后,它就发送给从服务器去进行载入。在更新状态完成之后,Master再将记录在缓冲区里面的新命令发送给从服务器,这样从服务器进行执行,主从服务器就保持了一致状态。
从服务器到主服务器的复制可以分为两种情况:

  1. 初次复制
  2. 断链后的重复制
    初次复制就是进行建立连接,然后进行全量和增量的同步,它的SYNC命令可以很好地完成任务。 但对于断线后的重复制,处于命令传播阶段的主从服务器因为网络原因而中断又重连,会再次发送SYNC命令做全量+增量同步效率较低。 SYNC命令是一个非常耗费资源的操作,资源包括CPU、内存、磁盘、带宽、流量等。

PSYNC同步

为了解决SYNC在处理断线重复制时候的低效问题,Redis从2.8版本之后开始使用PSYNC命 令,它支持完整重同步和部分重同步。 完整重同步和SYNC一样,部分重同步就是在处理断 线重新连接之后,主节点只向从节点发送链接断开期间的写命令,它的实现基于以下三部分:

  1. 复制偏移量(replication offset)
    Master:每次向Slave发送n个字节数据时,就会将自己的offset+n;
    Slave:每次收到Master发送来的n个字节数据时,就会将自己的offset+n;
    如果主从服务器处于一致状态,那么Master和Slave的Offset总是相同的。
  2. 复制积压缓冲区(replication backlog)
    Master上维护的每一个固定大小(fixed-size)的FIFO队列,保存着一部分最近传播的写命令。
    Master进行命令传播时,不仅会将命令发送给所有Slave,还会将写命令入队到复制积压缓 冲区。
    复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量,Slave重连Master时,会通过PSYNC命令将自己的Offset发送给Master。它是一个环形缓冲区,大小是固定的,可存储的命令有限,超出部分将会被删除。
  3. Replication ID(复制ID)
    每个Redis的主节点都用一个随机生成的字符串来表示在某一时刻其内部存储数据的状态, “某一时刻”可以理解为其成为master角色的那一刻,在第一个从节点加入时,Redis初始化了复制ID。
  4. 如果Slave的Offset与Master的Offset不相等,并且Slave的Offset偏移量之后的数据仍存在于replication backlog中,那么Master将对Slave执行部分重同步操作;
  5. 否则,需要执行完整重同步操作。

缺点:

  1. 在链式的一主两从的结构中,M -> S1-> S2,如果S1下线了,那么S2在成为M的从库后,会进行完全重同步;
  2. 在树状的一主两从的结构中,S1 -> M <- S2,如果M不可用下线,S1提升为主,那 么S2在成为S1的从库后,会进行完全重同步;
  3. 在一主一从的结构中,M -> S, 发生主从切换,需要进行完全重同步;
  4. 在从实例发生重启,及时不变更主从关系,由于丢失了所有的复制信息,还是会进行完全重同步;

PYSNC2

注:上述所有场景的前提是数据依然保存在backlog中,否则还是会进行完全重同步。

Redis命令传播原理

主从数据一致性

如果slave可以收到每条传播指令,并执行成功,便可以保持与master的数据一致状态。但是master并不等待slave节点的返回,master与slave是通过网络通信,由于网络抖动等因 素,命令传播过程不保证slave真正接收到,那如何在传播阶段确保主从数据一致呢?
在命令传播阶段,每隔一秒slave节点向master节点发送一次心跳信息,命令格式为 REPLCONF ACK <offset>。其中offset指从节点保存的复制偏移量。REPLCONF ACK命令的作用包括:

  1. 实时监测主从节点网络状态
    该命令会被主节点用于复制超时的判断。此外在主节点中使用info Replication,可以看到其从节点的状态中的lag值,代表的是主节点上次收到该 REPLCONF ACK命令的时间间隔,在正常情况下,该值应该是0或1。
  2. 检测命令丢失
    从节点发送了自身的offset,主节点会与自己的offset对比,如果从节点数据缺失(如网络丢包),主节点会推送缺失的数据(这里也会利用复制积压缓冲区)。 注意,offset和复制积压缓冲区,不仅可以用于部分复制,也可以用于处理命令丢失等情 形;区别在于前者是在断线重连后进行的,而后者是在主从节点没有断线的情况下进行的。
  3. 辅助保证从节点的数量和延迟
    Redis主节点中使用min-slaves-to-write和min-slaves-max-lag参数,来保证主节点在不安全的情况下不会执行写命令;所谓不安全,是指从节点数量太少,或延迟过高。例如min-slaves-to-write和min-slaves-max-lag分别是3和10,含义是如果从节点数量小于3个,或所有从节点的延迟值都大于10s,则主节点拒绝执行写命令。 而这里从节点延迟值的获取,就是通过主节点接收到REPLCONF ACK命令的时间来判断的,即前面所说的info Replication中的lag值。

全量同步和增量同步

在全量复制阶段,主节点会将执行的写命令放到复制缓冲区中,该缓冲区存放的数据包括了以下几个时间段内主节点执行的写命令:bgsave生成RDB文件、RDB文件由主节点发往从 节点、从节点清空老数据并载入RDB文件中的数据。当主节点数据量较大,或者主从节点之间网络延迟较大时,可能导致该缓冲区的大小超过了限制,此时主节点会断开与从节点之间的连接;这种情况可能引起全量复制→复制缓冲区溢出导致连接中断→重连→全量复制→复制缓冲区溢出导致连接中断......的循环。
复制缓冲区的大小由client-output-buffer-limit slave{hard limit}{soft limit}{soft seconds}配 置,默认值为client-output-buffer-limit slave 256MB 64MB 60,其含义是:如果buffer大于 256MB,或者连续60s大于64MB,则主节点会断开与该从节点的连接。该参数是可以通过 config set命令动态配置的(即不重启Redis也可以生效)。

backlog

Redis为复制积压缓冲区设置的默认大小为1MB,如果主服务器需要执行大量写命令,又或者主从服务器断线后重连接所需的时间比较⻓,那么这个大小也许并不合适。如果复制积压 缓冲区的大小设置得不恰当,那么PSYNC命令的复制重同步模式就不能正常发挥作用,正确估算和设置复制积压缓冲区的大小非常重要。
复制积压缓冲区的最小大小可以根据公式second*write_size_per_second 来估算:

上一篇 下一篇

猜你喜欢

热点阅读