Redis入门(四)主从复制
发布日期:2022-03-04 11:48:23 浏览次数:6 分类:技术文章

本文共 8265 字,大约阅读时间需要 27 分钟。

目录


第十一章 Redis主从复制

11.1 简介

   主从复制,即master/slaver机制,是指将一台Redis服务器的数据,复制到其他的Redis服务器,主机数据更新后根据配置和策略,自动同步到备机中。前者称为主节点master,后者称为从节点slave,master以写为主,slave以读为主。数据的复制是单向的,只能由主节点到从节点。

   默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点一主多从

   作用:

        ①读写分离,性能扩展

        ②容灾快速恢复(当一台从机宕机了,另一台从机可以继续工作)

11.2 运用实例---一主两从

11.2.1 创建目录,复制配置文件

   在根目录下创建一个myredis文件夹,将/etc/redis.conf配置文件复制到myredis文件夹中,并且将配置文件中的appendonly改为no,即关闭AOF。

11.2.2 新建三个配置文件

   因为本文是只在一台虚拟机上运行,为了演示,开启多台redis,需要不同的配置文件,使用不同的端口号。

        ①新建redis6379.conf:

        ②新建redis6380.conf:

        ③新建redis6381.conf:

11.2.3 启动三个Redis服务

   目前还没有配置主从关系,使用命令info replication可以查看主从复制的相关信息。

   使用redis-cli -p 端口号来开启进入三个Redis服务器的客户端,然后查看信息:

11.2.4 配置从机

   命令:

        slaveof <ip> <port>

   在6380、6381两个redis服务器上执行该命令,作为从机:

11.2.5 主写从读操作

   在master上写:

   在slave上读:

11.2.6 一主二仆

   当一个从服务器挂掉了,重启之后不会自动变为从服务器,而是初始为主服务器。如果此时再把该服务器设置成之前服务器的从服务器,会把主服务器中的数据从头复制一份

   当主服务器挂掉了,此时从服务器不会做任何事情,仍旧是该主服务器的从服务器,当主服务器重启后,还是这些从服务器的主服务器。

11.2.7 薪火相传

   上一个slave可以是下一个slave的master,slave同样可以接受其他slave的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力,去中心化降低奉献。

   仍旧是命令slaveof <ip> <port>。

   中途变更转向会清楚之前额数据,重新建立拷贝最新的。

   风险是一旦某个slave宕机,后面的slave都没法备份。

   主机挂了,从机还是从机,无法写数据了。

11.2.8 反客为主

   当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。

   命令:

        slaveof no one

11.3 主从复制原理

   参考:

   主从复制过程大体可以分为3个阶段:连接建立阶段(准备阶段)、数据同步阶段、命令传播阶段。

11.3.1 连接建立阶段

   该阶段的主要作用是在主从节点之间建立连接,为数据同步做好准备。

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

   ②建立socket连接:从节点每秒1次调用复制定时函数replicationCron(),如果发现了有主节点可以连接,便会根据主节点的ip和port,创建socket连接。如果连接成功,则:

        从节点:为该socket建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如

      接收RDB文件、接收命令传播等。

        主节点:接收到从节点的socket连接后(即accept之后),为该socket创建相应的客户端状

      态,并将从节点看做是连接到主节点的一个客户端,后面的步骤会以从节点向主节点发送命令

      请求的形式来进行

   ③发送ping命令:从节点成为主节点的客户端之后,发送ping命令进行首次请求,目的是:检查socket连接是否可用,以及主节点当前是否能够处理请求。从节点发送ping命令后,可能出现3种情况:

        1.返回pong:说明socket连接正常,且主节点当前可以处理请求,复制过程继续。

        2.超时:一定时间后从节点仍未收到主节点的回复,说明socket连接不可用,则从节点断开

          socket连接,并重连。

        3.返回pong以外的结果:如果主节点返回其他结果,如正在处理超时运行的脚本,说明主节

          点当前无法处理命令,则从节点断开socket连接,并重连。

   ④身份验证:如果从节点中设置了masterauth选项,则从节点需要向主节点进行身份验证;没有设置该选项,则不需要验证。从节点进行身份验证是通过向主节点发送auth命令进行的,auth命令的参数即为配置文件中的masterauth的值。如果主节点设置密码的状态,与从节点masterauth的状态一致(一致是指都存在,且密码相同,或者都不存在),则身份验证通过,复制过程继续;如果不一致,则从节点断开socket连接,并重连。

   ⑤发送从节点端口信息:身份验证之后,从节点会向主节点发送其监听的端口号(前述例子中为6380),主节点将该信息保存到该从节点对应的客户端的slave_listening_port字段中;该端口信息除了在主节点中执行info Replication时显示以外,没有其他作用。

11.3.2 数据同步阶段

   主从节点之间的连接建立以后,便可以开始进行数据同步,该阶段可以理解为从节点数据的初始化。具体执行的方式是:从节点向主节点发送psync命令(Redis2.8以前是sync命令),开始同步。

   需要注意的是,在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及以后,主从节点互为客户端。原因在于:在此之前,主节点只需要响应从节点的请求即可,不需要主动发请求,而在数据同步阶段和后面的命令传播阶段,主节点需要主动向从节点发送请求(如推送缓冲区中的写命令),才能完成复制。

11.3.3 命令传播阶段

   数据同步阶段完成后,主从节点进入命令传播阶段。在这个阶段主节点将自己执行的写命令发送给从节点(互为客户端),从节点接收命令并执行,从而保证主从节点数据的一致性。

   在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING和REPLCONF ACK

   命令传播是异步的过程,即主节点发送写命令后并不会等待从节点的回复,因此实际上主从节点之间很难保持实时的一致性,延迟在所难免。

11.3.4 总结

   1.slave启动成功连接到master后会发送一个psync命令;

   2.Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。

        同步机制分为全量复制和增量复制。

        全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。

        增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步。

   3.只要是重新连接master,一次完全同步(全量复制)将被自动执行

11.4 全量复制和部分复制

   在Redis2.8以前,从节点向主节点发送sync命令请求同步数据,此时的同步方式是全量复制;在Redis2.8及以后,从节点可以发送psync命令请求同步数据,此时根据主从节点当前状态的不同,同步方式可能是全量复制或部分复制。

11.4.1 全量复制

   用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。

   过程:

        ①从节点判断无法进行部分复制,向主节点发送全量复制的请求;或从节点发送部分复制的

          请求,但主节点判断无法进行部分复制;

        ②主节点收到全量复制的命令后,执行bgsave,在后台生成RDB文件,并使用一个缓冲区(称

          为复制缓冲区主节点会为每一个从节点分别分配复制缓冲区)记录从现在开始执行的所有写

          命令;

        ③主节点的bgsave执行完成后,将RDB文件发送给从节点;从节点首先清除自己的旧数据

          然后载入接收的RDB文件,将数据库状态更新至主节点执行bgsave时的数据库状态;

        ④主节点将前述复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据

          库状态更新至主节点的最新状态;

        ⑤如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的

          最新状态。

   整个过程中,需要传输的就是两部分:RDB文件 + 复制缓冲区的记录

11.4.2 部分复制

   用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。

   部分复制的实现,依赖于三个重要的概念:

        ①复制偏移量:主节点和从节点分别维护一个复制偏移量(offset),代表的是主节点向从节

          点传递的字节数;主节点每次向从节点传播N个字节数据时,主节点的offset增加N;从节点

          每次收到主节点传来的N个字节数据时,从节点的offset增加N。ffset用于判断主从节点的数

          据库状态是否一致:如果二者offset相同,则一致;如果offset不同,则不一致,此时可以根

          据两个offset找出从节点缺少的那部分数据。

        ②复制积压缓冲区:复制积压缓冲区是由主节点维护的、固定长度的、先进先出(FIFO)队

          列,默认大小1MB;当主节点开始有从节点时创建,其作用是备份主节点最近发送给从节点

          的数据。注意,无论主节点有一个还是多个从节点,都只需要一个复制积压缓冲区(一个主节

          点只有一个)。在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积

          压缓冲区,作为写命令的备份,除了存储写命令,复制积压缓冲区中还存储了其中的每个字

          节对应的复制偏移量(offset)。由于复制积压缓冲区定长且是先进先出,所以它保存的是主节

          点最近执行的写命令;时间较早的写命令会被挤出缓冲区。由于该缓冲区长度固定且有限,

          因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执

          行部分复制,只能执行全量复制。从节点将offset发送给主节点后,主节点根据offset和缓冲

          区大小决定能否执行部分复制:如果offset偏移量之后的数据,仍然都在复制积压缓冲区

          里,则执行部分复制;如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤

          出),则执行全量复制。

        ③服务器运行ID:每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都

          不一样),由40个随机的十六进制字符组成;runid用来唯一识别一个Redis节点。通过info

          Server命令,可以查看节点的runid。主从节点初次复制时,主节点将自己的runid发送给从

          节点,从节点将这个runid保存起来。当断线重连时,从节点会将这个runid发送给主节点,

          主节点根据runid判断能否进行部分复制:如果从节点保存的runid与主节点现在的runid相

          同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看

          offset和复制积压缓冲区的情况);如果从节点保存的runid与主节点现在的runid不同,说明从

          节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。

11.5 psync命令的执行

   执行过程如下图:

首先,从节点根据当前状态,决定如何调用psync命令:

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

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

  • 如果主节点版本低于Redis2.8,则返回-ERR回复,此时从节点重新发送sync命令执行全量复制;
  • 如果主节点版本够新,且runid与从节点发送的runid相同,且从节点发送的offset之后的数据在复制积压缓冲区中都存在,则回复+CONTINUE,表示将进行部分复制,从节点等待主节点发送其缺少的数据即可;
  • 如果主节点版本够新,但是runid与从节点发送的runid不同,或从节点发送的offset之后的数据已不在复制积压缓冲区中(在队列中被挤出了),则回复+FULLRESYNC <runid> <offset>,表示要进行全量复制,其中runid表示主节点当前的runid,offset表示主节点当前的offset,从节点保存这两个值,以备使用。

11.6 心跳机制

   心跳机制对于主从复制的超时判断、数据安全等有作用。

11.6.1 主->从:PING

   每隔指定的时间,主节点会向从节点发送PING命令(官方文档是说从节点向主节点发送PING命令的),这个PING命令的作用,主要是为了让从节点进行超时判断。PING发送的频率由repl-ping-slave-period参数控制,单位是秒,默认值是10s。

11.6.2 从->主:REPLCONF ACK

   在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令,频率是每秒1次。

   命令格式为:REPLCONF ACK {offset},其中offset指从节点保存的复制偏移量。

   REPLCONF ACK命令的作用包括:

        ①实时监测主从节点网络状态:该命令会被主节点用于复制超时的判断。此外,在主节点中

          使用info Replication,可以看到其从节点的状态中的lag值,代表的是主节点上次收到该

          REPLCONF ACK命令的时间间隔,在正常情况下,该值应该是0或1。

        ②检测命令丢失:从节点发送了自身的offset,主节点会与自己的offset对比,如果从节点数据

          缺失(如网络丢包),主节点会推送缺失的数据(这里也会利用复制积压缓冲区)。

          注意:offset和复制积压缓冲区,不仅可以用于部分复制,也可以用于处理命令丢失等情形;

          区别在于前者是在断线重连后进行的,而后者是在主从节点没有断线的情况下进行的。

        ③辅助保证从节点的数量和延迟: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值。

11.7 哨兵模式

   参考:

11.7.1 简介

   Redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移。可以理解为反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从节点转换为主节点。一个哨兵可以监控多个节点

   功能:

        ①监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。

        ②自动故障转移(Automatic failover):当主节点不能正常工作时,哨兵会开始自动故障转移操

          作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的

          主节点。

        ③配置提供者(Configuration provider):客户端在初始化时,通过连接哨兵来获得当前Redis

          服务的主节点地址。

        ④通知(Notification):哨兵可以将故障转移的结果发送给客户端。

11.7.2 架构

   由两部分组成:

        哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据

        数据节点:主节点和从节点都是数据节点

   哨兵节点本质上就是redis节点

11.7.3 使用步骤

   依旧是上面的一主二仆模式,主节点是6379,从节点是6380、6381。

  • 新建自定义sentinel.conf文件(文件名字不能出错),配置哨兵,填写内容:

sentinel monitor mymaster 127.0.0.1 6379 1

mymaster:为监控对象起的服务器名称,别名

1:至少需要有多少个哨兵同意迁移的数量

  • 启动哨兵:redis-sentinel sentinel.conf。哨兵进程的端口号为26379

  • 当主机挂掉了,会在从机中产生新的主机。怎么选择?

        此时哨兵节点启动和故障转移阶段,各个节点的配置文件会被重写。对于主从节点,主要是

      slaveof配置的变化:新的主节点没有了slaveof配置,其从节点则slaveof新的主节点。对于哨

      兵节点,除了主从节点信息的变化,纪元(epoch)也会变化。

        优先级的配置参数:replica-priority。默认100,值越小,优先级越高。

        偏移量是上文提到的offset,runid也是上文提及的每个节点的一个id。

11.7.4 基本原理

   关于哨兵的原理,关键是了解以下几个概念:

        ①定时任务:每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:通过向主从节点

          发送info命令获取最新的主从结构;通过发布订阅功能获取其他哨兵节点的信息;通过向其

          他节点发送ping命令进行心跳检测,判断是否下线。

        ②主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就

          会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主

          观下线相对应的是客观下线。

        ③客观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr

          命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则

          对该主节点进行客观下线。

            需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被

          哨兵主观下线后,不会再有后续的客观下线和故障转移操作。

        ④选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出

          一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。

            监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法Raft算法的

          基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意

          过其他哨兵,则会同意A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵

          选择的过程很快,谁先完成客观下线,一般就能成为领导者。

        ⑤故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:

  • 在从节点中选择新的主节点:选择的原则是,首先过滤掉不健康的从节点;然后选择优先级最高的从节点(由slave-priority指定);如果优先级无法区分,则选择复制偏移量最大的从节点;如果仍无法区分,则选择runid最小的从节点。
  • 更新主从状态:通过slaveof no one命令,让选出来的从节点成为主节点;并通过slaveof命令让其他节点成为其从节点。
  • 将已经下线的主节点(即6379)设置为新的主节点的从节点,当6379重新上线后,它会成为新的主节点的从节点。

PS:根据尚硅谷视频整理,如有侵权,联系删除。

转载地址:https://blog.csdn.net/xxyneymar/article/details/122466680 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:力扣题59螺旋矩阵II
下一篇:Redis入门(五)集群

发表评论

最新留言

很好
[***.229.124.182]2024年04月11日 05时57分56秒