Redis之主从复制的实现

Redis高可用的方案包括持久化、主从复制(及读写分离)、哨兵和集群。这边文章就来介绍一些Redis的复制功能。

在Redis中,用户可以通过执行SLAVEOF命令或设置salveof选项,让一个服务器去复制另一个服务器,我们称被复制的服务器叫主服务器(master),对主服务器进行复制的服务器叫做从服务器(slave)。
在这里插入图片描述

为什么要使用主从复制
  • 当主服务器挂掉之后,从服务器可以继续工作,从而实现快速的故障恢复,可以看做是数据备份。
  • 在主从复制的基础上实现读写分离,即写在主服务器(master),读在从服务器(slave)。尤其是在写少读多的场景下,通过多个从节点分担负载,可以大大提高Redis服务器的并发量。
  • 另外主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
  • 还有一种情况,当redis想要扩容的时候,单机是满足不了,所以必须要有从服务器(slave)。
复制功能的实现

Redis 的复制功能分为同步(psync)和命令传播(command propagate)两个操作:

  • 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。psync命令具有完整同步和部分同步的的两种模式
    • 完整同步:用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。通过向主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步
    • 部分同步:部分同步主要处理断线之后的场景。当服务器在断线之后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器断开连接期间执行的写命令发送给从服务器,从服务只需要接受并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。部分同步需要以下三个功能协助完成:
      • 主服务器的偏移量(offset)
      • 主服务器的复制挤压缓冲区(默认大小1M)
      • 服务器的运行ID
  • 命令传播操作则用于在主服务器的数据库状态被修改, 导致主从服务器的数据库状态出现不一致时, 让主从服务器的数据库重新回到一致状态

主从复制主要分为三个阶段:建立连接(数据准备)、数据同步和命令广播。接下来分别介绍一下这三个阶段。

建立连接阶段
  • 保存主节点信息。

从节点服务器内部维护了两个字段,即masterhost和masterport字段,用于存储主节点的ip和port信息。需要注意的是,slaveof是异步命令,从节点完成主节点ip和port的保存后,向发送slaveof命令的客户端直接返回OK,实际的复制操作在这之后才开始进行。

  • 建立socket连接
  • 发送ping命令
  • 身份验证
  • 发送从节点端口信息
数据同步阶段

当连接建立好之后,就可以开始进行同步了。这一步是主从复制最重要的一步,具体执行的方式是:从节点向主节点发送psync命令(Redis2.8以前是sync命令),开始同步,根据主从节点当前状态的不同,可以分为完整同步部分复制

在这里插入图片描述
完整复制流程可以大概总结为:

(1)从节点判断无法进行部分复制,向主节点发送全量复制的请求;或从节点发送部分复制的请求,但主节点判断无法进行部分复制;具体判断过程需要在讲述了部分复制原理后再介绍。

(2)主节点收到全量复制的命令后,执行bgsave,在后台生成RDB文件,并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令

(3)主节点的bgsave执行完成后,将RDB文件发送给从节点;从节点首先清除自己的旧数据,然后载入接收的RDB文件,将数据库状态更新至主节点执行bgsave时的数据库状态

(4)主节点将前述复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据库状态更新至主节点的最新状态

(5)如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的最新状态

部分同步的实现:
在这里插入图片描述
首先,从节点根据当前状态,决定如何调用psync命令:

  • 如果从节点之前未执行过slaveof或最近执行了slaveof no one,则从节点发送命令为psync ? -1,向主节点请求全量复制;
  • 如果从节点之前执行了slaveof,则发送命令为psync ,其中runid为上次复制的主节点的runid,offset为上次复制截止时从节点保存的复制偏移量。

主节点根据收到的psync命令,及当前服务器状态,决定执行全量复制还是部分复制:

  • 如果主节点版本低于Redis2.8,则返回-ERR回复,此时从节点重新发送sync命令执行全量复制;
  • 如果主节点版本够新,且runid与从节点发送的runid相同,且从节点发送的offset之后的数据在复制积压缓冲区中都存在,则回复+CONTINUE,表示将进行部分复制,从节点等待主节点发送其缺少的数据即可;
  • 如果主节点版本够新,但是runid与从节点发送的runid不同,或从节点发送的offset之后的数据已不在复制积压缓冲区中(在队列中被挤出了),则回复+FULLRESYNC <runid> <offset>,表示要进行全量复制,其中runid表示主节点当前的runid,offset表示主节点当前的offset,从节点保存这两个值,以备使用。
命令广播
  • 主->从(PING命令):每隔指定的时间,主节点会向从节点发送PING命令,这个PING命令的作用,主要是为了让从节点进行超时判断。单位是秒,默认值是10s。
  • 从->主(REPLCONF ACK命令):在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令,频率是每秒1次;命令格式为:REPLCONF ACK {offset},其中offset指从节点保存的复制偏移量。
总结
  • 主从复制的作用:宏观的了解主从复制是为了解决什么样的问题,即数据备份、故障恢复、读写分离、哨兵和集群的基础等。
  • 主从复制的操作:即slaveof命令。
  • 主从复制的原理:主从复制包括了连接建立阶段、数据同步阶段、命令传播阶段;其中数据同步阶段,有全量复制和部分复制两种数据同步方式;命令传播阶段,主从节点之间有PING和REPLCONF ACK命令互相进行心跳检测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值