Redis多机数据库

news2024/12/29 8:39:53

文章目录

  • Redis多机数据库
    • 一、主从复制
      • 1、旧版复制功能的实现
        • a、同步
        • b、命令传播
      • 2、旧版复制功能的缺陷
      • 3、新版复制功能的实现
        • a、部分同步功能
        • b、复制实现步骤
      • 4、心跳检测
    • 二、哨兵
      • 1、Sentinel概念
      • 2、Sentinel初始化流程
      • 3、故障转移过程
    • 三、集群
      • 1、几个概念
      • 2、集群创建流程
        • a、启动节点
        • b、槽指派
      • 3、集群执行命令流程
        • moved错误
        • slots_to_keys
      • 4、重分片流程
        • ask错误
      • 5、伸缩流程
      • 6、故障转移流程
      • 7、消息

Redis多机数据库

Redis数据结构与对象:https://blog.csdn.net/qq_41822345/article/details/130456081
Redis单机数据库:https://blog.csdn.net/qq_41822345/article/details/130909789

先总结一下Redis的四种部署模式(除了第一种是单机数据库,其它都是多机数据库):

  • 1、单机模式

    • 概念:Redis单机模式是最简单的部署模式,Redis将数据存储在单个节点上。

    • 优点

      • 简单易用。架构简单,部署方便。
      • 低延迟高性能。毕竟是单机,少了很多的网络传输。
    • 缺点

      • 无法保证数据的可靠性。
      • 处理能力有限。受限于单核CPU的处理能力。
      • 内存容量有限 。因此一般不会用于生产环境。
  • 2、主从复制模式

    • 概念:主从模式是指可以让一个服务器(slave)去复制另一个服务器(master)的数据。

    • 优点

      • 数据备份。Master能自动将数据同步到Slave,且同步是以非阻塞bgsave的方式进行的。
      • 读写分离。 分担Master的读压力。
    • 缺点

      • 不具备自动容错与恢复功能。
      • 有数据不一致的风险。比如master宕机。
      • 难以支持在线扩容,Redis的容量仍然受限于单机配置
  • 3、哨兵模式

    • 概念: 哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。

    • 优点

      • 主从复制模式有的优点,哨兵模式也有。
      • 系统可用性更高。master挂掉可以自动进行切换。
    • 缺点

      • 主从复制模式有的优点,哨兵模式也有。
      • 需要额外的资源来启动sentinel进程,实现相对复杂一点。
  • 4、集群模式

    • 概念:集群模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题。

    • 优点

      • 无中心架构。
      • 可维护性。降低运维成本,提高系统的扩展性和可用性。
      • 高可扩展。可线性扩展到1000多个节点,节点可动态添加或删除。
      • 高可用性。部分节点不可用时,集群仍可用。
    • 缺点

      • 架构复杂性。客户端实现的复杂性。开发难度提高。
      • 数据通过异步复制,不保证数据的强一致性。
      • slave节点只能作为数据备份,不能缓解读压力。
      • 不支持多数据库,只有1个数据库空间db0。
      • 运维复杂,需要面临更多问题:比如Key事务操作、big-key/hot-key的处理更加复杂。

一、主从复制

主从模式是指通过执行 slaveof 命令或设置 slaveof 选项,让一个服务器(slave)去复制另一个服务器(master)的数据。

只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。

主从复制是哨兵和集群能够实施的基础,因此可以说主从复制是Redis高可用的基石。

1、旧版复制功能的实现

Redis的复制功能分为 同步命令传播 两个操作。

a、同步

一个redis实例变成另一个redis实例的从节点有三种方式。

  • 启动前:在从服务器的配置文件中加入slaveof配置;
  • 启动时:在redis-server启动命令后加入–slaveof;
  • 启动后:直接在客户端执行命令:slaveof ,则该Redis实例成为从节点。

当redis实例通过上述方式变成一个从节点后,首先要执行同步操作——通过向主服务器发送SYNC命令来完成,步骤如下:

  • step1:从服务节点向主服务器发送sync命令;
  • step2:主服务节点执行bgsave命令,后台生成RDB文件的同时,并使用缓冲区记录之后的所有写命令;
  • step3:主服务节点将生成的RDB文件发送给从服务器;
  • step4:从服务节点载入RDB文件,将自己的数据库状态更新至主服务节点执行bgsave命令时的数据库状态;
  • step5:主服务器将缓冲区的所有写命令发送给从服务器;
  • step6:从服务器执行这些写命令,将自己与主服务节点完全同步。
b、命令传播

当主服务器执行新的写命令时,主从服务器就可能出现不一致状态。这时主服务器需要对从服务器执行命令传播操作:将写命令传播给从服务器,这也是从服务器唯一能接收写命令的方式。

2、旧版复制功能的缺陷

以上复制方式在从节点初次复制主节点时,没有什么问题,但是当断线后重复制时,从节点需要再次发送sync命令,相当于初次复制。这种为了让从服务器补足一小部分缺失的数据,但却要把所有数据重新复制一遍的做法是非常低效的。

  • SYNC 命令是一个非常耗费资源的操作【非必要时不要执行这个命令】
    • 主服务器需要执行 bgsave 命令,这需要耗费主服务器大量的CPU、内存和I/O资源。
    • 主服务器将RDB文件发送给从服务器,这占用主服务器和从服务器大量的网络资源。
    • 从服务器在载入RDB文件的期间,会因为阻塞无法处理其它命令请求。

3、新版复制功能的实现

从Redis2.8版本开始,使用 PSYNC 代替 SYNC 命令,它有两种模式:完整同步模式和部分同步模式。

完整同步模式用于处理复制,等同于旧版复制功能。

部分同步模式解决了旧版复制功能在处理断线后重复制时出现的低效问题。

部分同步模式只需要将从服务器缺少的写命令发送给从服务器执行就可以了。

a、部分同步功能

部分同步功能的实现基于以下三个部分构成:

  • 复制偏移量offset

  • 复制积压缓冲区

  • 服务器的运行ID

    实现原理简述:从服务器发生断连时,它会向主服务器发送PSYNC 主服务器运行ID 复制偏移量offset 请求进行部分同步。主服务器接收到从服务器的PSYNC命令之后,首先对比从服务器传来的 主服务器运行ID ,如果和自己一致,那就检测从复制偏移量offset之后的数据是否存在于复制积压缓冲区,如果存在,则响应 +CONTINUE回复给从服务器,表示可以进行部分同步操作。

b、复制实现步骤
  • 1、连接建立阶段【主从服务器状态属性中互相保存IP:port的过程】

    • step1、保存主节点信息

      从服务器节点执行完slave of命令之后,会将主服务器的IP:port保存到从服务器节点状态中的masterhost属性和masterport属性,然后返回OK给客户端。

    • step2、建立socket连接

      从服务器根据step1中保存的IP:port,创建连向主服务器的socket。主服务器在accept从服务器的连接之后,也会创建相应的socket。至此,主从服务器将基于此socket对进行通信。

    • step3、发送ping命令

      从服务器向主服务器发出ping进行连接测试,如果收到响应pong说明连接测试成功。否则断开连接并重连master。

    • step4、身份验证

      如果需要认证【主从双方都配置了密码】,则进行认证成功之后才能进行下一步。

    • step5、发送从节点端口信息

      从服务器执行命令 replconf litsten-port port 向主服务器发送端口。主服务状态中属性中保存从服务器的IP:port。

  • 2、数据同步阶段

    • step1、首先,从节点根据当前状态,决定如何调用 psync命令。
      • 全量复制:用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。
      • 部分复制:用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。
    • step2、主节点根据收到的 psync 命令,及当前服务器状态,决定执行全量复制还是部分复制。
      • 如果主节点版本低于Redis2.8,则返回-ERR回复,此时从节点重新发送 sync 命令执行全量复制;
      • 如果主节点版本够新,且runid与从节点发送的runid相同,且从节点发送的offset之后的数据在复制积压缓冲区中都存在,则回复 +CONTINUE,表示将进行部分复制,从节点等待主节点发送其缺少的数据即可;
      • 如果主节点版本够新,但是runid与从节点发送的runid不同,或从节点发送的offset之后的数据已不在复制积压缓冲区中(在队列中被挤出了),则回复 +FULLRESYNC ,表示要进行全量复制,其中runid表示主节点当前的runid,offset表示主节点当前的offset,从节点保存这两个值,以备使用。
  • 3、命令传播阶段

    • step1、在这个阶段主节点将自己执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一致性。
    • step2、在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PINGREPLCONF ACK

4、心跳检测

主服务器通过向从服务器传播命令来更新从服务器的状态,保持主从服务器一致,同时从服务器也需要通过向主服务器发送 replconf ack 命令(每秒一次)来进行心跳检测。

心跳检测有三个作用:

  • 1、检测主从服务器的网络连接状态

    主服务器如果有超过1秒的时间没有收到来自从服务器的心跳检测命令 replconf ack ,那么主服务器就知道主从服务器之间的连接有问题了。通过 info replication 命令可以看到从服务器最后一次向主服务器的心跳检测过了多少秒。一般延迟(lag)值在0到1秒之间属于正常。

  • 2、辅助实现min-slaves配置选项

    主服务器一般会配有设置 min-slaves-to-writemin-slaves-max-lag 参数。表示如果slave少于 min-slaves-to-write 个 或者有 min-slaves-to-write 个slave的延迟(lag)都不小于 min-slaves-max-lag秒,则主服务器拒绝写命令。

  • 3、检测命令丢失

    从服务器会在发送 replconf ack 命令中告诉主服务器自己的复制偏移量offset,主服务器如果发现偏移量比自己少,就知道有命令发生的丢失,这时主服务器会从自己的复制积压区找到从服务器缺少的数据,重新发送给从服务器。(补发缺失数据 与 部分重同步原理一样【都是Redis 2.8版本新增的功能】,它们的区别是前者未发生断连,只是丢失了某些命令,而后者属于发生了断线并重连)

二、哨兵

哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。

由一个或多个Sentinel去监听(并且Sentinel也可以互相监视)任意多个主服务以及主服务器下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线的主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已经下线的主服务器继续处理命令请求。

1、Sentinel概念

  • Sentinel 本质上只是一个运行在特殊模式下的Redis服务器。

  • Sentinel可以监控任意多个Master和该Master下的Slaves( 即多个主从模式) 。

  • 在同一个Sentinel哨兵下的,不同主从模型彼此之间相互独立,

  • Sentinel的三个任务

    • 监控

      Sentinel 会不断地检查主服务器和从服务器是否运作正常。

    • 提醒

      当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

    • 自动故障迁移

      当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作,将其中一个从服务器升级为新的主服务器。

  • Sentinel网络

    • sentinel本身是监督者的身份,没有存储功能。
    • 监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器的信息。
    • 在整个体系中一个sentinel者或一群sentinels与主从服务架构体系是监督与被监督的关系。
    • 为什么需要一个这样的Sentinel网络?
      • sentinel在整个架构体系中有如下三种交互:sentinel与主服务器、sentinel与从服务器、sentinel与其他sentinel。
      • 既然是交互,首先无可避免的就要构建这样的一个交互网络,需要节点的注册与发现、节点之间的通信连接、节点保活、节点之间的通信协议等。

2、Sentinel初始化流程

Redis在哨兵模式下,在监控主从服务器之间,需要先完成Sentinel节点的初始化。流程如下:

  • step1、启动并初始化Sentinel。

    执行 redis-sentinel /path/to/your/sentinel.conf 命令 或者 redis-server /path/to/your/sentinel.conf --sentinel 命令

    • a、使用Sentinel专用代码。

      Sentinel模式下Redis服务器只有以下功能:

      • 复制命令,比如slaveof
      • 发布与订阅功能,比如publish和subscribe
      • 文件事件处理器,比如负责发送命令请求、处理命令回复
      • 时间事件处理器,负责执行serverCron函数
    • b、初始化Sentinel状态,即初始化sentinalState结构

    • c、初始化Sentinel状态中的Master属性

    • d、创建连向主服务器的网络连接

  • step2、获取主服务器信息(每10秒一次)

  • step3、获取从服务器信息(每10秒一次)

  • step4、向主/从服务器发送信息(每2秒一次)

  • step5、接收来自主服务器和从服务器的频道信息

    • sentinel与主从服务器之间需要创建两种连接,一个是命令连接,一个是订阅连接。

    • sentinel需要通过命令连接向主从服务器发送信息,同时也需要通过订阅连接从主从服务器那接收信息。

    • 通过交换信息,来进行下面的步骤。

  • step6、更新Sentinel字典

  • step7、创建连向其它Sentinel的命令连接

    • 当一个Sentinel通过订阅连接从主服务器那获取到其它Sentinel时,它不仅会更新Sentinel字典中的实例结构,还会和新Sentinel之间互相创建新的命令连接最终监视同一个主服务器的多个Sentinel形成了相互连接的Sentinel网络

Sentinel模式下的服务器状态如图

在这里插入图片描述

3、故障转移过程

Sentinel模式下,Sentinel初始化完成之后,在Sentinel网络中对所有的Matser和Slave进行监控。如果这时出现主服务器故障,则走如下流程。

  • step1、判定主观下线(每1秒一次)

    Sentinel会向所有与它创建了命令连接实例(包括主服务器、从服务器、其它Sentinel)发送Ping命令。并根据有效回复 Pong-Loading-Matserdown (其它回复均为无效回复)进行检测。如果超过 down-after-milliseconds毫秒都没有有效回复,Sentinel就会把matser标记为主观下线。

    down-after-milliseconds也是Sentinel判断master属下的slave,以及监视该matser的其它Sentinel是否进入主观下线的标准。

  • step2、判定客观下线

    当Sentinel检测到主观下线后,就会询问其它监视该master的Sentinel,当超过一定数量的Sentinel都认为该Master已经下线后,就会将主服务器判定为客观下线。

    • a、Sentinel发送is-matser-down-by-addr命令,对其它Sentinel进行询问
    • b、其它Sentinel接收is-matser-down-by-addr命令,分析并检查master是否下线,并做出回复。
    • c、Sentinel接收回复,对回复进行统计。当超过一定数量的Sentinel都认为该Master已经下线后,就会将主服务器判定为客观下线。
  • step3、选举Sentinel Leader【基于Raft协议

    当检测出客观下线后,所有监视这个下线master的Sentinel需要先进行leader选举,由领导Sentinel进行故障转移操作。

    • a、任何Sentinel都有成为leader的机会。每进行一次选择,Sentinel的epoch就会自增一次。
    • b、每个发现master客观下线的Sentinel都会要求其它Sentinel将投自己一票,每个Sentinel都有一票,规则是先到先得。
    • c、源Sentinel接收其它目标Sentinel的回复,并判断回复中epoch和leader-runid,如果epoch相同,并且leader-runid就是自己,那么说明目标Sentinel认可自己作为局部leader。
    • d、当某个Sentinel被超过半数以上的Sentinel认可,那么这个Sentinel就会从局部leader成为全局leader,即领头Sentinel。
    • e、因为每个Sentinel只有一票,且需要超过半数的投票,所有每个配置纪元epoch中最多只会有一个Sentinel被选举为leader。
    • f、如果在给定的时间内,没有选举出leader,那么epoch+1,重新进行一次选举。
  • step4、选举新的主服务器。这是由领头Sentinel会在所有Slave中选出新的Master,选举规则如下:

    • a、删除列表中所有处于下线或者短线状态的Slave。
    • b、删除列表中所有最近5s内没有回复过领头Sentinel的INFO命令的Slave。
    • c、删除所有与下线Master连接断开超过down-after-milliseconds * 10毫秒的Slave。
    • d、领头Sentinel将根据Slave优先级,对列表中剩余的Slave进行排序,并选出其中优先级最高的Slave。
    • e、如果有多个具有相同优先级的Slave,那么领头Sentinel将按照Slave复制偏移量,选出其中偏移量最大的Slave。
    • f、如果有多个优先级最高,偏移量最大的Slave,那么根据运行ID最小原则选出新的Master。
  • step5、让其余所有Slave服务器复制新的Master服务器。

  • step6、当下线的Master重新上线后,将它变成新的Master服务器的Slave。

三、集群

Redis集群是由Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能。

  • RedisCluster 是 Redis 的亲儿子,它是 Redis 作者自己提供的 Redis 集群化方案。
  • redis在3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的数据。cluster模式为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器,内存/QPS不受限于单机,可受益于分布式集群高扩展性。
  • Redis Cluster是一种服务器Sharding技术(分片和路由都是在服务端实现),采用多主多从,每一个分区都是由一个Redis主机和多个从机组成,片区和片区之间是相互平行的。

相关参考:

Redis Cluster数据分片实现原理、及请求路由实现:https://blog.csdn.net/Seky_fei/article/details/107611850
Redis集群 - 图解 - 秒懂(史上最全):https://www.cnblogs.com/crazymakercircle/p/14698576.html#autoid-h3-7-0-0

  • Redis 集群方案主要有3类:
    • 1、基于官方的 Redis cluster 的服务端分片方案。(分片和路由都是在服务端实现)
    • 2、使用类 codis 的代理模式架构,按组划分,实例之间互相独立。(分片和路由在代理实现)
    • 3、代理模式和服务端分片相结合的模式。

1、几个概念

  • 集群cluster、节点node、槽slot、键key之间的关系

    • cluster:node = 1:n

    • node:slot = 1:n

    • slot:key = 1:n

  • 什么是槽slot?

    Redis Cluster是Redis3.0引入的一种无中心化的集群,客户端可以向任何一个节点通信,Redis Cluster将数据的key通过将CRC16算法的结果取模16383后,分给16384个slot槽,集群的每个节点负责一部分hash槽,节点只负责管理映射到这个槽的KV数据,对于不是当前槽的KV数据,会向客户端发送一个MOVED,表示需要客户端重新重定向到其它节点。

  • 为什么引入槽slot?

    • 解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
    • 节点自身维护槽的映射关系,不需要客户端 或 代理服务维护数据分片关系。
    • Redis Cluster的节点之间会共享消息,每个节点都知道另外节点负责管理的槽范围。每个节点只能对自己负责的槽进行维护 和 读写操作。
  • 为什么没有使用一致性hash算法,而是使用了哈希槽预分片?

    • 一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
    • 当服务节点太少或者有节点挂掉时,容易造成数据倾斜——大量的缓存数据集中到了一台或者几台服务节点上。
  • 为什么是16384个槽位(2^14)?

    • 如果槽位是16384个,发送心跳信息的消息头是16384/8/1024 = 2k。
    • Redis的集群主节点数量一般不会超过1000个。
    • 集群中节点越多,心跳包的消息体内的数据就越多,如果节点过多,也会造成网络拥堵。
    • 对于节点数在1000个以内的Redis Cluster,16384个槽位完全够用。

2、集群创建流程

集群创建流程就是一个创建集群实例数据结构体(一定都会有的结构体:redisServer、redisClient;集群模式下才有数据:clusterNode、clutserLink、clutserState等)的过程。

a、启动节点
  • Redis服务器在启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式。

  • Redis节点在集群模式下会继续使用所有在单机模式中使用的服务器组件

    • 文件事件处理器:处理命令请求和返回命令回复
    • 时间事件处理器:执行serverCron函数(这时该函数也执行在集群模式下需要执行的操作:发送Gossip消息、下线检测、故障转移等)
    • redisDb数据库:保存键值对。不过集群模式下只有db0数据库。
    • redisServer/redisClient数据结构:保存服务器状态和客户端状态。
    • 持久化:RDB和AOF持久化。
  • 初始化集群模式下数据结构:

    • clusterNode:每个节点都会使用一个clusterNode来记录自己的节点状态——比如节点名称、ip和端口、slot信息等。
    • clutserLink:保存连接节点所需的有关信息——比如socket套接字、输入缓冲区/输出缓冲区等。
    • clutserState:每个节点都会使用一个clutserState来记录当前节点在集群中的状态——比如配置纪元、集群节点名单、槽指派信息等。
  • cluster meet命令

    该命令用于将一个节点加入到集群中。这个过程类似三次握手,先由节点A向节点B发送meet消息;节点B返回pong消息给节点A,这是对meet消息的确认;最后节点A还会发送一次ping消息给节点B,告诉节点B收到了B的pong消息,至此握手完成。

  • Gossip协议

    通过Gossip协议传播新节点的加入,让其它节点也与新节点进行握手。最终所有节点都会认识新节点。

b、槽指派
  • Redis集群的整个数据库被分为16384个槽slot,每个slot都必须分配到某个节点上,否则集群将处于下线状态。

  • 节点的clusterNode结构记录了节点的槽指派信息。

    • slots属性记录了节点负责处理槽信息。numslots属性记录了当前节点负责处理的槽数量
    • slots是一个二进制位数组。长度为16384/8=2048,每个slots[i]有8位二进制,代表了16384个槽。
  • 传播节点的槽指派信息

    每个节点都会将自己的slots数组通过消息发送给集群中的其它节点。这样集群中的每个节点都会知道所有的槽指派信息。

  • 记录集群的槽指派信息

    集群的槽指派信息当然是记录在clutserState.slots中,它的每个数据项都是一个指向clusterNode结构的指针。

    • clutserNode.slots数组只记录了当前节点的槽指派信息。
    • clutserState.slots数组记录了全部节点的槽指派信息。
  • cluster addslots命令

    通过该命令将槽指派给执行该命令的节点。

3、集群执行命令流程

当客户端向节点发送与数据库键key有关的命令时,需要经过以下步骤:

  • step1:计算键属于哪个槽

    CRC16(key)& 16383

  • step2:判断槽是否由当前节点负责处理

    根据step1计算出一个值 i 之后,判断clutserState.slots[i] = clutserState.myself

  • step3:如果clutserState.slots[i] != clutserState.myself。则根据clutserState.slots[i]所指向的clutserNode结构,获取IP:port,通过moved错误返回给客户端,从而转向负责处理槽slots[i]的节点。

moved错误

当节点发现键 key 所在的槽 slot[i] 并非由自己负责处理的时候,节点就会返回给客户端一个moved错误(包含了正确的负责处理槽 slot[i] 的节点),从而指引客户端专项正在负责槽的节点。

客户端会先根据moved错误提供的IP地址和端口来连接节点,然后再进行转向。

slots_to_keys

clutserState.slots_to_keys是一个跳跃表,它保存了槽与键之间的关系。通过记录各个数据库键所属的槽,节点可以很方便的对属于某个或某些槽的所有数据库键进行批量操作。比如重新分片。

4、重分片流程

Redis集群的重新分片操作是由管理组件redis-trib负责执行的,它通过向源节点和目标节点发送命令来进行重新分片操作步骤以及执行的命令如下:

  • step1:开始对槽slot进行重新分片操作

  • step2:通知目标节点准备导入槽slot的键值对;cluster setslot slot_id importing source_id

  • step3:通知源节点准备迁移槽slot的键值对;cluster setslot slot_id migrating target_id

  • step4:向源节点获取最多count个属于槽slot的键值对;cluster getkeyinslot slot_id count

  • step5:将step4获取的每个键迁移到目标节点(通过pipeline 机制批量迁移);migrate target_id target_port kets

  • step6:重复执行step4和step5,直到属于槽slot的所有keys都被迁移完毕。

  • step7:传播槽指派信息;任意发送cluster setslot slot_id node target_id命令给某个节点,最终会通过Gossip协议传播给整个集群。

如果重新分片涉及到多个槽slot,那么redis-trib对于每个槽分别执行上面的操作。

ask错误

moved错误和ask错误的区别?

  • 区别在于槽slot[i]目前由哪个节点负责。

    • 对于moved错误,说明slot[i]由其它节点负责,之后对于slot[i]的操作会直接发送到负责它的节点。
    • 对于ask错误,说明slot[i]正在进行重分片,slot[i]的负责节点还在迁移中。
  • 当客户端向某个节点发送命令,节点向客户端返回moved异常,告诉客户端数据对应的槽的节点信息;客户端再向正确的节点发送命令时,如果此时正在进行集群扩展或者缩空操作,槽及槽中数据已经被迁移到别的节点了,就会返回ask,这就是ask重定向机制。

5、伸缩流程

Redis集群中的每个node(节点)负责分摊这16384个slot中的一部分,也就是说,每个slot都对应一个node负责处理。当动态添加或减少node节点时,只需要将16384个槽做个再分配,将槽中的键值和对应的数据迁移到对应的节点上。

redis cluster提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容,也可以下线部分节点进行缩容。可以说,槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动。

集群的伸缩流程原理基于重新分片原理。

  • a、集群扩容

    当一个 Redis 新节点运行并加入现有集群后,我们需要为其迁移槽和槽对应的数据。首先要为新节点指定槽的迁移计划,会确保迁移后每个节点负责相似数量的槽,从而保证这些节点的数据均匀。

  • b、集群收缩

    • 首先需要确认下线节点是否有负责的槽,如果有,需要把槽和对应的数据迁移到其它节点,保证节点下线后整个集群槽节点映射的完整性。
    • 当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记改节点后可以正常关闭。

6、故障转移流程

Redis集群的节点分为Master和Slave,其中Master负责处理槽slot,而从节点slave用于复制master(一个节点成为从节点,并开始复制某个主节点的这一信息会通过消息发送给集群中的其它节点,最终集群中的所有节点都会知道这一信息),并可以在master下线时,代替下线主节点成为新主节点继续处理命令请求。

  • step1、故障检测

    • 集群中的每个节点都会定期的向集群中的其它节点发送ping信息,来检测对方是否在线。
    • 集群中的各个节点会通过互相发送消息的方式来交换集群中各个节点的状态信息——比如某个节点是否处于疑似下线状态(PFail)、还是已下线状态(Fail)。
    • 集群中超过半数的matser节点都认为某个master节点为疑似下线状态(PFail),那么该master节点将被标记为已下线状态(Fail)。
  • step2、故障转移

    • 1、当一个从节点发现自己的主节点为已下线状态(Fail),从节点会要求集群中的其它主节点选举新的主节点。(同样也是基于Raft协议。并且与选举领头Sentinel的流程非常相似。)
    • 2、被选中的从节点执行slave of no one成为新的主节点。
    • 3、新的主节点会主动撤销所有对已下线主节点的槽指派,并将槽指派给自己。
    • 4、新的主节点向集群传播自己接管了下线的主节点。
    • 5、新的主节点开始接收属于自己负责的槽的key命令。故障转移完成。

7、消息

Redis集群中的各个节点通过发送和接收消息来进行通信。节点发送的消息主要有以下五种:

  • 1、meet消息:节点加入集群的命令。
  • 2、ping消息:用于检测节点是否在线。集群中的每个节点每隔一秒就会从已知节点的列表中随机选择5个节点进行ping检测。如果当前节点发现自己记录的某些节点回复pong消息的时间超过了当前节点设置的cluster-node-timeout选线设置时长的一半,则当前节点主动发送ping检测,防止自己长时间都没有随机选择到某些节点进行ping检测,造成信息更新滞后。
  • 3、pong消息:用于响应meet消息或者ping消息。也可用于向集群广播pong消息以刷新其它节点对自己的认识。
  • Redis集群中各个节点通过Gossip协议来交换自己知道的节点状态消息。Gossip协议的实现由meet、ping、pong三种消息实现,它们都由clusterMsgDataGossip结构组成。
  • 每次发送meet、ping、pong消息时,发送者都会从自己的已知节点列表中随机选出两个节点的信息(包括节点名称、ip和端口等)保存到要发送的消息结构体clusterMsgDataGossip结构里面。
  • 4、fail消息:用于告知集群中的其它节点有节点进入fail状态。

在集群的节点数量比较大的情况下,单纯的使用Gossip协议来传播节点的已下线信息会给节点的信息更新带来一定的延迟,因为这个协议通常需要一段时间才能传播至整个集群,而发送Fail消息会让集群里的所有节点立即知道某个主节点已经下线,从而尽快判断是否需要将集群标记为下线,又或者对下线主节点进行故障转移。

  • 5、publish消息:当节点接收到某个publish命令时,不仅会执行这个命令,并向集群广播这条publish命令。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1260737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

西南科技大学(数据结构A)期末自测练习一

一、填空题(每空0.5分,共5分) 1、数据结构是指( A )。 A、数据元素的组织形式 B、数据类型 C、数据存储结构 D、数据定义 2、数据结构被形式地定义为(D,R),其中D是( B )的有限集合,R是D上( D )的有限集合。 (1)A.算法B.数据元素C.数据操作D.逻辑结构 (2)A.操作B.…

springboot启动Table ‘xxx‘ already exists

jpa.generate-ddl和jpa.hibernate.ddl-auto都可以控制是否执行datasource.schema脚本,来初始化数据库结构,只要有一个为可执行状态就会执行,比如jpa.generate-ddl:true或jpa.generate-ddl:update,并没有相互制约上下级的关系。 要…

使用com组件编辑word

一个普通的窗体应用,6个button using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; u…

Kafka 如何保证消息消费的全局顺序性

哈喽大家好,我是咸鱼 今天我们继续来讲一讲 Kafka 当有消息被生产出来的时候,如果没有指定分区或者指定 key ,那么消费会按照【轮询】的方式均匀地分配到所有可用分区中,但不一定按照分区顺序来分配 我们知道,在 Kaf…

【操作宝典】SQL Server Management

目录 ⛳️【SQL Server Management】 ⛳️1. 启动登录 ⛳️2. 忘记密码 ⛳️3. 操作数据库和表 3.1 新建数据库text 3.2 新建表 3.3 编辑表 3.4 编写脚本 ⛳️【SQL Server Management】 ⛳️1. 启动登录 需要开启服务 ⛳️2. 忘记密码 登录windows--> 安全性 -->…

优雅使用docker-compose部署Skywalking

Skywalking使用docker-compose部署 version: 3.1 services: // 部署elasetic search 用于存储获取的应用信息与日志elasticsearch:image: elasticsearch:7.13.3container_name: elasticsearchprivileged: trueenvironment:- "cluster.nameelasticsearch" #设置集群名…

Vue3使用kkFileView预览文件pdf

kkFileView - 在线文件预览kkFileView官网 - kkFileView使用Spring Boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,Excel,pdf,txt,zip,rar,图片等等https://kkfileview.keking.cn/zh-cn/docs/usage.html业务场景&#xf…

powershell获取微软o365 21v日志

0x00 背景 o365 21v为o365的大陆版本,主要给国内用户使用。微软提供了powershell工具和接口获取云上日志。微软o365国内的代理目前是世纪互联。本文介绍如何用powershell和配置证书拉取云上日志。 0x01 实践 第一步,ip权限开通: 由世纪互联…

生命科学领域 - 新药从研发到上市全流程

新药是指新研制的、临床尚未应用的药物,其化学本质应为新的化合物或称新化学实体、 新 分子实体、新活性实体。新药研发的根本目的是治疗疑难危重疾病,研制出来的药物即使是全新的化学结构,但是疗效或安全性却不及现有的药物便失去新药价值&a…

JAVAEE 初阶 多线程基础(三)

启动,中断,等待基础 一.如何创建线程二.启动线程 start()1.1 调用两次start方法1.2 创建新对象解决多个start问题2.1 经典面试题 run和start的区别 三.中止线程3.1 引入标志位3.2 高级写法3.3高级写法的错误之处3.4问题的解决3.5 将标志位放在main的局部变量中是否可行 四.等待…

Android 单元测试初体验(二)-断言

[TOC](Android 单元测试初体验(二)-断言) 前言 当初在学校学安卓的时候,老师敢教学进度,翻到单元测试这一章节的时候提了两句,没有把单元测试当重点讲,只是说我们工作中几乎不会用到,果真在之前的几年工作当中我真的没…

flutter布局详解及代码示例(上)

布局 基本布局 Row(水平布局):在水平(X轴)方向上排列子widget的列表。Column(垂直布局):在垂直(Y轴)方向上排列子widget的列表。Stack(可重叠布…

【九章斩题录】Leetcode:面试题 01.03. URL化(C/C++)

精品题解 🔥 《九章斩题录》 👈 猛戳订阅 面试题 01.03. URL化 📚 题目:URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。…

本地训练,立等可取,30秒音频素材复刻霉霉讲中文音色基于Bert-VITS2V2.0.2

之前我们使用Bert-VITS2V2.0.2版本对现有的原神数据集进行了本地训练,但如果克隆对象脱离了原神角色,我们就需要自己构建数据集了,事实上,深度学习模型的性能和泛化能力都依托于所使用的数据集的质量和多样性,本次我们…

使用最小花费爬楼梯(力扣LeetCode)动态规划

使用最小花费爬楼梯 题目描述 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶…

Springboot日志-logback

logback-spring.xml的配置项 共有一个父标签、两种属性、三个节点: 一个父标签&#xff1a;configuration 两种属性&#xff1a;contextName和property 三个节点&#xff1a;appender、root、logger 日志级别 日志级别从低到高分为TRACE < DEBUG < INFO < WARN &…

telnet-MISC-bugku-解题步骤

——CTF解题专栏—— 题目信息&#xff1a; 题目&#xff1a;这是一张单纯的图片 作者&#xff1a;未知 提示&#xff1a;无 解题附件&#xff1a; 解题思路&#xff1a; (⊙﹏⊙)这是个什么文件pcap文件分析_pcap文件打开-CSDN博客查了一下&#xff0c;但没看懂&#xff0c…

人工智能关键技术决定机器人产业的前途

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指让计算机或机器具有类似于人类的智能和学习能力的技术。人工智能技术与机器人技术的结合将改变传统的机器人行业格局&#xff0c;就像智能手机对传统手机的颠覆一样。本文从人工智能技术的发展趋势、…

使用STM32和蓝牙模块进行无线数据传输的实践

无线数据传输在现代通信领域中具有重要的地位&#xff0c;而蓝牙技术是一种常用的无线数据传输技术。本文介绍了如何使用STM32微控制器和蓝牙模块实现无线数据传输的方案&#xff0c;包括硬件设计、蓝牙模块配置、数据发送和接收等步骤&#xff0c;并给出相应的代码示例。 一、…

从中序与后序遍历序列构造二叉树(C++实现)

从中序与后序遍历序列构造二叉树 题目思路代码代码讲解 题目 力扣&#xff1a;从中序与后序遍历序列构造二叉树 思路 代码 class Solution { public:TreeNode* _build(vector<int>& inorder, vector<int>& postorder,int & peri,int lefti,int right…