• Redis】Redis主从复制(二)————主从结构/流程


    回顾

    主从结构中 redis 从节点上只能读数据,不能写入数据,主节点写入的数据,在从节点都能查看并获取到
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    slaveof 命令

    断开主从复制关系

    • 在当前从节点的 redis 客户端中使用 slaveof no one 可以断开现有的主从复制关系,并且自身成为新的主节点
      在这里插入图片描述
    • 这里从节点断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化
      在这里插入图片描述在这里插入图片描述在这里插入图片描述

    切换主从复制关系

    • 通过 slaveof 命令还可以实现切主操作,将当前从节点的数据源切换到另⼀个主节点,并且切换后会先删除当前节点的所有数据,再复制新的主节点数据。执行 slaveof 新主节点IP 新主节点端口 命令即可。

    • 例如将端口号为 6381 从节点的 “主”,换成 端口号为 6380,如下
      在这里插入图片描述

    • 现在的情况就是6379是6380的主节点,6380是6381的主节点

    • 而且此处的修改是临时的,如果重启 redis 服务器,就会按照最初再配置文件中设置的内容来建立主从关系

    只读

    要设置Redis的主从复制为只读模式,可以通过修改从节点的配置文件来实现。

    • 首先,在主节点的配置文件redis.conf中,设置slave-read-only参数为yes:

      slave-read-only yes
      
    • 然后,在从节点的配置文件redis.conf中,设置slave-read-only参数为yes,并且设置masterauth参数来保护主节点的写操作:

      slave-read-only yes
      masterauth 
      
    • 其中,是主节点的密码。

    • 保存并关闭配置文件后,重新启动从节点即可。从节点在只读模式下,将无法接受任何写入操作,只能进行读取操作。如果有写入操作,从节点将抛出错误。

    • 确保从节点处于只读模式后,可以通过在从节点上执行redis-cli info命令来验证。在输出的信息中查找role:slave,并确保master_replidmaster_repl_offset等参数被正确地设置为主节点的信息。

    • 由于复制只能从主节点到从节 点,对于从节点的任何修改主节点都⽆法感知,修改从节点会造成主从数据不⼀致。所以建议线上不要修改从节点的只读模式。

    网络延迟问题

    Redis主从复制中的网络延迟问题是指主节点与从节点之间进行数据同步时所出现的网络延迟现象。

    • 在Redis主从复制中,主节点将自己的写操作记录在内存中的AOF日志或者RDB文件中,并且将这些写操作发送给从节点,从节点则通过执行这些写操作来保持与主节点的数据同步。

    • 然而,由于网络的不稳定性或者网络带宽的限制,主节点发送给从节点的数据可能会发生延迟。这可能导致从节点在执行主节点的写操作之前会有一段时间的数据不一致。

    • 例如,如果主节点发送的写操作在发送之前就出现了网络延迟,从节点可能会在这段延迟期间没有接收到新的写操作,并且从节点上的数据可能会落后于主节点。

    • 这种网络延迟问题可能会导致主节点和从节点之间的数据不一致,特别是在高写入负载下或者网络环境较差的情况下。

    应对措施

    1. 尽量减少网络延迟:确保主节点和从节点之间的网络连接质量良好,并尽量采用高带宽、低延迟的网络环境。

    2. 监控网络延迟:通过监控工具或者Redis的内置命令,实时监测主从节点之间的网络延迟情况,及时发现和解决延迟问题。

    3. 设置Redis复制的超时时间:通过设置适当的超时时间,可以确保主节点和从节点之间的数据同步不会因为网络延迟而无法完成。

    4. 使用命令等待复制完成:在从节点执行写操作之前,可以使用Redis的命令等待功能,等待主节点的数据同步完成后再执行写操作,以保证数据一致性。

    5. 增加从节点的数量:使用多个从节点可以减轻单个从节点的负载,并且增加了数据同步的冗余性,能够更好地应对网络延迟问题。

    补充

    • TCP 内部支持 naqle 算法,目的就是为了节省网络带宽(目的和 tcp 的捎带应答一样,针对小的 tcp 数据报,就多攒点,攒够了再发,这样就减少了发送的次数)。
    • 通过 repl-disable-tcp-nodelay 这个选项就可以进行配置 naqle 算法是否开启.
    • 值得注意的是,实际的工作中,需要根据实际场景来决定是否开启:
      • 开启,能节省网络带宽,但是会增加 tcp 的传输延迟.
      • 关闭,能减少 tcp 传输延迟,但是会增加网络带宽.
    • 一般游戏开发,或者是视频直播,这种即时性要求特别强的,就像需要关闭 naqle 算法.

    主从结构

    一主一从结构

    主节点有一个从节点,主节点负责处理写操作,从节点负责复制主节点的数据并处理读请求。

          +--------+
          | Master |
          +--------+
             |
             |
             v
          +--------+
          |  Slave |
          +--------+
    
    • 这种结构有一个特点,就是当写请求的数据太多的时候,也会给主节点带来压力,可以通过关闭主节点的 AOF ,只在从节点上开启 AOF 来分担持久化压力,避免影响性能。

    问题

    • 这种设定方式有一个缺陷,就是主节点一旦挂了,就不能让他自动重启
    • 如果自动重启,此时没有 AOF 文件就会丢失数据,进一步的同步到从节点上,就会把 从节点的数据也给搞丢了.

    改进

    • 改进的办法就是当主节点挂了以后,让主节点从从节点这里获取 AOF 文件再启动.
    • 实际的开发中,读请求 远远超过 写请求,也难辞上述的 一主一从结构就有点难以应对了,就需要一主多从结构来支持
      Redis主从结构主要有以下两种:

    一主多从结构

    主节点可以有多个从节点,主节点负责处理写操作,从节点负责复制主节点的数据并处理读请求。

          +--------+
          | Master |
          +--------+
             |
             |
             v
          +--------+
          |  Slave |
          +--------+
             |
             |
             v
          +--------+
          |  Slave |
          +--------+
    
    • 这种结构就是适合有大量到读请求场景,帮助主节点分担大部分的 读请求 压力
    • 但实际随着从节点个数的增加,向主节点中写入一条数据,就需要同步给多个从节点,反而影响性能.

    树形主从

    				            +--------+
    				            | Master |
    				            +--------+
    				               |
    				               |
    			   +-------------------------------------+
    			   |                          			 |
    			   v                          			 v
    			+--------+                			 +--------+
    			| Slave1 |                			 | Slave2 |
       +---------------------------+                 +--------+
       |                           |					 |
       |                           |					 |
       v                           v				 	 v
    +--------+                 +--------+			 +--------+
    | Slave3 |                 | Slave4 |		     | Slave4 |
    +--------+                 +--------+			 +--------+
    
    • 这种结构,从节点也可以将其他从节点当作主节点,分担了主节点将数据同步到从节点上的压力,但是一旦数据进行修改,同步的延时是要比刚才更长的

    主从切换结构

    多个主节点通过复制数据到各自的从节点,从节点可以作为主节点的备份,当主节点发生故障时,可以将其中一个从节点切换为新的主节点。

          +--------+          +--------+
          | Master |          | Master |
          +--------+          +--------+
             |                    |
             |                    |
             v                    v
          +--------+          +--------+
          |  Slave |          |  Slave |
          +--------+          +--------+
    

    主从复制流程

    Redis主从复制是一种数据同步机制,它允许将一个Redis服务器(主服务器)的数据复制到多个其他Redis服务器(从服务器)。下面是Redis主从复制的详细流程:

    1. 从服务器连接主服务器:从服务器通过向主服务器发送SYNC命令来与主服务器建立连接。

    2. 主服务器执行BGSAVE命令:主服务器收到SYNC命令后,执行BGSAVE命令将当前数据库状态保存到磁盘上的RDB文件中。

    3. 主服务器发送RDB文件:当BGSAVE命令完成后,主服务器将RDB文件发送给从服务器。

    4. 从服务器接收RDB文件:从服务器接收到RDB文件后,将其写入本地磁盘。

    5. 主服务器发送缓冲区数据:主服务器将在RDB文件生成期间接收到的所有命令写入到缓冲区。

    6. 主服务器发送缓冲区数据偏移量:当RDB文件发送完毕后,主服务器将发送缓冲区数据的偏移量给从服务器。

    7. 从服务器请求增量数据:从服务器收到缓冲区数据偏移量后,向主服务器发送PSYNC命令,请求增量数据。

    8. 主服务器发送增量数据:主服务器收到PSYNC命令后,将缓冲区数据偏移量之后的所有命令发送给从服务器。

    9. 从服务器执行增量数据:从服务器接收到增量数据后,将其执行,使自己的数据库与主服务器保持一致。

    10. 主从服务器保持同步:主服务器会持续地把接收到的写命令发送给从服务器,从服务器会实时地执行这些命令,以保持与主服务器的数据同步。

    简单来记

    1. 保存主节点信息
    2. 主从建立连接:通过 TCP 三次握手建立连接,主要是为了验证通信双方是否能正确的读写数据(道路能否建立起来).
    3. 验证主节点是否能够正常工作:发送 ping 命令
    4. 权限验证:redis 主节点如果设置了密码参数,就需要先通过密码的验证.
    5. 同步数据集
    6. 命令持续复制:当从节点复制完主节点的所有数据后,主节点还会“源源不断”的收到写请求,机会继续将修改后的数据复制到从节点上.

    关于数据同步

    • 其实就是上面第七步开始,Redis 使用 psync 命令完成主从数据同步,从节点会自动执行 psync,也就是从节点会去主节点这边拉取数据:psync replicationid offset

    两个参数

    replicationid
    • replication id 就表示要从那个主节点上获取数据.
    • replication id 是由主节点生成的,生成的时机是在,主节点启动的时候会生成(同一主节点,每次重启,生成的 replication id 都是不同的),从节点晋升为主节点的时候也会生成。
    • 当从节点和主节点建立了复制关系,就会从主节点这边拉取到 replication id.
    • 通过 info replication 可以获取到当前 replication id 的值.
      在这里插入图片描述
    • 这里还可以看到 replid2,但是一般是用不上的
    • 有一个情况就是假设有两个节点,主节点 A 和 从节点 B,如果 A 和 B 通信的过程中出现了网络抖动,B 可能就认为 A 挂了,就会把 replid 的值交给 replid2,然后 B 就会自己成为主节点,给自己生成一个 replid,
    • 此时,B 也会记得之前的主节点 A 的 replid,就是现在的 replid2。
    • 等后续网络稳定了,B 还可以根据 replid2 重新回到 A 的怀抱(这里需要手动干预,但是哨兵机制可以自动完成)
    offset.

    在这里插入图片描述

    • 从节点和主节点之间的数据同步,不是瞬间完成的,并且在复制数据的同时,主节点上也会 “源源不断” 的收到其他 “修改数据” 的请求,那么从节点怎么知道数据已经同步到哪里了呢?

      • 主节点和从节点上都会维护一个偏移量(整数),主节点的偏移量,就是把收到的 “写操作” 的命令(每个命令都要占几个字节)按字节进行累加的.
      • 从节点的偏移量就描述了,现在从节点这里的数据同步到哪里了.
      • 如果从节点的偏移量和主节点偏移量一样了,就说明两个节点的数据完全一致了.
    • 在 psync 命令中,offset 有两种写法:

      • offset 写作 -1,就是获取全量数据.
      • offset 写成具体的正整数就是从当前偏移量位置来进行获取.

    psync 运行流程

    在这里插入图片描述
    PSYNC命令用于在Redis主从复制中请求增量数据的同步操作,下面是PSYNC命令的运行流程:

    1. 从服务器发送PSYNC命令:从服务器向主服务器发送PSYNC命令,带上自己的复制偏移量和复制ID。

    2. 主服务器判断复制模式:主服务器收到PSYNC命令后,首先会判断当前的复制模式。

      • 如果主服务器处于全量复制模式(即没有之前的复制关系),则主服务器将执行全量复制流程。

      • 如果主服务器处于部分复制模式(即已经有之前的复制关系),则主服务器将执行部分复制流程。

    3. 主服务器执行全量复制流程:

      a. 主服务器检查RDB文件:主服务器会检查自己是否有可用的RDB文件,以确定是否需要传输RDB文件给从服务器。如果有RDB文件,则进入步骤4;否则,进入步骤5。

      b. 主服务器发送RDB文件和缓冲区数据:主服务器将发送RDB文件和缓冲区数据给从服务器。

      c. 从服务器接收RDB文件和缓冲区数据:从服务器接收RDB文件和缓冲区数据后,将其写入本地磁盘,并执行缓冲区数据,使数据库与主服务器同步。

      d. 主服务器继续发送增量数据:主服务器会持续地把接收到的写命令发送给从服务器,从服务器会实时地执行这些命令,以保持与主服务器的数据同步。

    4. 主服务器执行部分复制流程:

      a. 主服务器检查复制ID:主服务器会根据从服务器发送的复制ID来检查是否有与之一致的复制积压数据。

      b. 主服务器发送增量数据:如果有一致的复制积压数据,主服务器将发送这些增量数据给从服务器;否则,进入步骤5。

      c. 从服务器接收增量数据:从服务器接收到增量数据后,将其执行,使自己的数据库与主服务器保持一致。

    5. 主服务器执行全量重同步流程:

      a. 主服务器发送FULLRESYNC命令:主服务器将发送FULLRESYNC命令给从服务器,带上自己的复制ID和最新的复制偏移量。

      b. 从服务器接收FULLRESYNC命令:从服务器接收到FULLRESYNC命令后,将其保存为自己的复制ID和复制偏移量。

      c. 主服务器发送RDB文件和缓冲区数据:主服务器将发送RDB文件和缓冲区数据给从服务器。

      d. 从服务器接收RDB文件和缓冲区数据:从服务器接收RDB文件和缓冲区数据后,将其写入本地磁盘,并执行缓冲区数据,使数据库与主服务器同步。

      e. 主服务器继续发送增量数据:主服务器会持续地把接收到的写命令发送给从服务器,从服务器会实时地执行这些命令,以保持与主服务器的数据同步。

    通过PSYNC命令的流程,主从服务器可以进行数据同步,保持数据的一致性。

    全量复制和部分复制
    • 全量复制:首次和主节点进行数据同步时(判断 replication id 不一样),或者是在部分复制的时候,发现已经超出积压缓冲区的数据范围了,也会进行全量复制.
      在这里插入图片描述

    • 部分复制:从节点之前从主节点上父之过数据了,或者是有网络抖动或者从节点重启而丢失数据(大部分数据是一致的).
      在这里插入图片描述

    全量复制流程:
    1. 从服务器向主服务器发送SYNC命令,请求进行复制。
    2. 主服务器收到SYNC命令后执行BGSAVE命令,将当前数据库状态保存到RDB文件中。
    3. 主服务器将生成的RDB文件发送给从服务器。
    4. 从服务器接收到RDB文件后,将其加载到内存中,更新自己的数据库状态。
    5. 主服务器将复制缓冲区中的命令发送给从服务器,从服务器执行这些命令,使自己与主服务器同步。
    6. 主服务器将继续发送增量数据给从服务器,从服务器实时执行这些命令来保持与主服务器的同步。
    部分复制流程:
    1. 从服务器向主服务器发送PSYNC命令,带上自己的复制ID和复制偏移量。
    2. 主服务器检查复制ID和偏移量,确定是否能进行部分复制。
      • 如果能进行部分复制,则主服务器将发送复制积压数据给从服务器,从服务器接收并更新自己的数据库状态。
      • 如果不能进行部分复制(例如主服务器没有该复制ID的积压数据),则主服务器执行全量同步流程。

    在部分复制流程中,主服务器会根据从服务器提供的复制ID查找是否有与之一致的复制积压数据,如果有,则将这些增量数据发送给从服务器进行同步。这样可以减少数据传输的量,提高复制的效率。如果没有一致的复制积压数据,主服务器会执行全量同步来实现复制。

    实时复制流程
    • 从节点和主节点数据同步完成了(也就是说这一刻,从节点和主节点数据一致了),但是之后,主节点这边也会 “源源不断” 的收到新的 “写请求” ,主节点上的数据就会随之改变,这种改变也需要能够同步给从节点.
    • 此时,从节点和主节点之间会建立 TCP 长连接,然后主节点把自己收到的 “写请求” 修改的数据,发给从节点,从节点再修改自己内存中的数据.
    • 这个过程也是需要时间的,正常来说,延时是比较短的,但是如果是多级从节点的树形结构,延时就会上升了.
    心跳包
    • 进行实时复制的时候,需要保证连接处于可用状态,因此引入了心跳包机制.
    • 主节点:默认,每隔 10s 给从节点发送一个 ping 命令,从节点收到就会返回 pong.
    • 从节点:默认,每隔 1s 就给主节点发起一个特定的请求,就会上报当前从节点的复制数据的进度(offset).
    • 如果主节点发现从节点通信延迟超过 repl-timeout 配置的值(默认 60 秒),则判定从节点下线,断 开复制客⼾端连接。从节点恢复连接后,⼼跳机制继续进⾏。

    补充

    通常主从复制肯定不是我们现在这样一个redis服务分三个端口开放,常规来说都是分别部署在不同的服务器上,这样也能避免一些问题,比如最开始创建从节点的配置文件没有改 appendfilename 属性,导致生成的 aof 文件路径/文件名 都是同一个

  • 相关阅读:
    【精选】矩阵加速
    每期一个小窍门: java线程池的几种任务拒绝策略
    iframe实现pdf预览,并使用pdf.js修改内嵌标题,解决乱码问题
    【算法】选择排序
    窗口置顶工具v2.0.0
    Mac RabbitMq 安装
    React事件与原生DOM事件的不同
    Redis缓存
    线性表的线性表示;初始化,输出,插入,删除,查找;
    第九章 动态规划 part16(编辑距离专题)583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇
  • 原文地址:https://blog.csdn.net/weixin_37833693/article/details/139602292