Redis多机数据库

文章目录

  • 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.rhkb.cn/news/207709.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

localStorage 和sessionStorage

localStorage 和 sessionStorage 是浏览器提供的两种客户端存储数据的方式: 生命周期: localStorage: 存储在 localStorage 中的数据在浏览器关闭后仍然保留,直到被显式删除或浏览器清除缓存。sessionStorage: 存储在 …

oops-framework框架 之 初始了解(一)

引擎:CocosCreator 环境: Mac Gitee: oops-framework 简介 oops-framework是由作者dgflash编写,基于CocosCreator 3.x而实现的开源框架。 该框架以插件形式存在,主要目的是为了降低与项目的耦合,并且通过插件内部的…

【QuickSort】单边快排思路及实现

思路: (1)首先定义一个递归函数:qucikSort(int [ ] arr,int l,int r)。函数的定义:给定一个数组arr,对它在[l,r]这个区间内的元素进行排序,从而使得整个数组在[l,r]这个区间内有序。 &#xff0…

电梯安全远程监控系统解决方案

一、方案背景 随着万丈高楼的平地起,电梯也成为了我们出入高层建筑最常用的工具之一。面对电梯数量的不断增加,电梯安全事故也是相继频发,因此关于电梯的安全运行就越来越受到社会各界的关注。电梯的使用在给人们出入高层建筑带来便利的同时&…

一种LED驱动专用控制电路方案

一、基本的概述 TM1651 是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。本产品性能优良,质量可靠。采用SOP16/DIP16的封装形式。 二、特性说…

金蝶Apusic应用服务器 任意文件上传漏洞复现

0x01 产品简介 金蝶Apusic应用服务器(Apusic Application Server,AAS)是一款标准、安全、高效、集成并具丰富功能的企业级应用服务器软件,全面支持JakartaEE8/9的技术规范,提供满足该规范的Web容器、EJB容器以及WebSer…

快速筛出EXCEL行中的重复项

比如A列是一些恶意IP需要导入防火墙,但包括一些重复项,为不产生错误,需要把重复项筛出来: 1、给A列排序,让重复项的内容排在相邻的行 2、在B列中写一个条件函数:IF(A1A2,1,0),然后下拉至行尾完成…

如何在 AdsPower 浏览器中设置代理

AdsPower是一款反检测指纹浏览器,来自中国开发团队的一款对电子商务营销人员非常有用的强大工具,同时具有出色的英语支持。AdsPower浏览器的主要优势是其价格便宜,与竞争对手相比,但其功能和整体工作表现甚至不逊于Indigo。 AdsP…

基于springboot+vue的点餐系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

IDEA编译器技巧-提示词忽略大小写

IDEA编译器技巧-提示词忽略大小写 写代码时,每次创建对象都要按住 Shift 字母 做大写开头, 废手, 下面通过编译器配置解放Shift 键 setting -> Editor -> General -> Code Completion -> Match case 把这个√去掉, 创建对象就不需要再按住 Shift 键 示例: 1.…

浅谈UML的概念和模型之UML九种图

1、用例图(use case diagrams) 【概念】描述用户需求,从用户的角度描述系统的功能 【描述方式】椭圆表示某个用例;人形符号表示角色 【目的】帮组开发团队以一种可视化的方式理解系统的功能需求 【用例图】 2、静态图 类图&…

ClassCMS2.4漏洞复现

CMS源码在附件中 环境搭建 使用phpstudy2016搭建web环境,php版本为5.5 安装CMS 这里选择Mysql数据库进行安装 用户名和密码都写默认的admin方便记忆 输入完成后点击安装 点击安装 CMS的安装过程中有个报错忽略就好,登录不进后台的话刷新一下页面 进入了C…

springboot数据格式验证——自定义日期格式验证及list验证

我们在工作中经常需要对日期格式进行定义,如果客户端传来的日期字符串不符合要求,那么根本无法保存,但是已有的注解并没有日期格式的验证,那我们就自己实现一个 一、自定义日期格式验证的注解DateFormat import javax.validatio…

Jquery动画特效

1&#xff0c;Jquery提供的特效方法 2&#xff0c;实例代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

反序列化漏洞详解(一)

目录 一、php面向对象 二、类 2.1 类的定义 2.2 类的修饰符介绍 三、序列化 3.1 序列化的作用 3.2 序列化之后的表达方式/格式 ① 简单序列化 ② 数组序列化 ③ 对象序列化 ④ 私有修饰符序列化 ⑤ 保护修饰符序列化 ⑥ 成员属性调用对象 序列化 四、反序列化 …

【C语言加油站】函数栈帧的创建与销毁 #保姆级讲解

函数栈帧的创建与销毁 导言一、计算机硬件1.冯•诺依曼机基本思想2.冯•诺依曼机的特点&#xff1a;3.存储器3.1 分类3.2 内存的工作方式3.3 内存的组成 4.寄存器4.1 基本含义4.2 寄存器的功能4.3 工作原理4.4 分类4.4.1 通用寄存器组AX(AH、AL)&#xff1a;累加器BX(BH、BL)&a…

【BEV感知 LSS方案】Lift-Splat-Shoot(LSS)

前言 LSS全称是Lift-Splat-Shoot&#xff0c;它先从车辆周围的多个摄像头拍摄到的图像进行特征提取&#xff0c;在特征图中估计出每个点的深度&#xff0c;然后把这些点“提升”到3D空间中。 接着&#xff0c;这些3D信息被放置到一个网格上&#xff0c;最后将这些信息“拍扁”…

Mybatis如何执行批量操作

文章目录 Mybatis如何执行批量操作使用foreach标签 使用ExecutorType.BATCH如何获取生成的主键 Mybatis如何执行批量操作 使用foreach标签 foreach的主要用在构建in条件中&#xff0c;它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有item&#xff0c;index&…

Unity中Shader指令优化

文章目录 前言一、解析一下不同运算所需的指令数1、常数基本运算2、变量基本运算3、条件语句、循环 和 函数 前言 上一篇文章中&#xff0c;我们解析了Shader解析后的代码。我们在这篇文章中来看怎么实现Shader指令优化 Unity中Shader指令优化&#xff08;编译后指令解析&…

qml ParticleSystem3D使用介绍

作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 在 Qt Quick 3D 中,ParticleSystem3D 是用来创建和控制3D粒子系统的元素。粒子系统是图形编程中用于模拟液体、烟雾、火、星空等现象的技术,它通过生成大量小粒子来模拟这些效果。Par…