欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis(九)--Redis集群

程序员文章站 2022-03-04 20:02:04
...

Redis(九)–Redis集群

这篇博客的内容主要包括以下:

  • 一、什么是Redis集群

  • 二、Redis集群模型

  • 三、各个节点之间都传递了什么信息

  • 四、 数据分布理论

    • 4.1 节点取余分区:

    • 4.2 一致性哈希分区

  • 五、Hash 槽

  • 六、容错

    • 新主的选举:
  • 七、Redis Cluster安装——原生安装

    • 7.1 理解架构
    • 7.2 原生安装——准备节点
    • 7.2 原生安装——节点握手 即meet操作
    • 7.3 原生安装——分配槽
    • 7.3 原生安装——分配主从
  • 八、 扩容集群

  • 九、在集群中执行命令:

    • 9.1 计算键属于哪个槽?
    • 9.2 判断槽是否由当前节点负责处理
    • 9.3.moved错误
  • 十、收缩集群

    • 10.1 下线迁移槽
    • 10.2 忘记节点
  • 十一、重新分片:

  • 十二、客户端路由

    • 12.1 moved 重定向
    • 12.2 ASK重定向
  • 十三、故障转移:

  • 补充的几道题:

    • 1,redis-cluster集群的特点:
    • 2,为什么使用redis-cluster?
    • 3,数据分片模型
    • 4,redis集群有哪几种形式(原理及优缺点)
    • 5,是否使用过redis集群,集群的原理是什么?
    • 6,什么时候整个集群不可用?
    • 7,哨兵模式和集群模式的区别?

一、什么是Redis集群

Redis 集群是一个分布式(distributed)、容错(fault-tolerant)的 Redis 实现, 集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集(subset)。

Redis 集群中不存在中心(central)节点或者代理(proxy)节点, 集群的其中一个主要设计目标是达到线性可扩展性(linear scalability)。

Redis 集群提供了一种运行 Redis 的方式,其中数据在多个 Redis 节点间自动分区。Redis 集群还在分区期间提供一定程度的可用性,即在实际情况下能够在某些节点发生故障或无法通信时继续运行。但是,如果发生较大故障(例如,大多数主站不可用时),集群会停止运行。

redis集群实现了对redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N

redis集群通过分区来提供一定程度的可用性:即使集群中有一部分节点失效(如果是大部分出现失效,则集群是不能使用的)或无法实现通讯,集群也可以继续处理命令请求

二、Redis集群模型

Redis(九)--Redis集群

  • 1):所有的节点通过服务通道直接相连,各个节点之间通过二进制协议优化传输的速度和带宽。
  • 2):客户端与节点之间通过 ascii 协议进行通信
  • 3):客户端与节点直连,不需要中间 Proxy 层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  • 4):尽管这些节点彼此相连,功能相同,但是仍然分为两种节点:master 和 slave。

三、各个节点之间都传递了什么信息

Redis(九)--Redis集群
通过上面的图我们可以知道各个节点之间通过 PING-PONG 机制通信,下面是一段关于 PING-PONG 机制的会话”内容”。

  • 节点M:PING,嘿,朋友你好吗?我是 XYZ 哈希槽的 master ,配置信息是 FF89X1JK。
  • 节点N:PONG,我很好朋友,我也是 XYZ 哈希槽的 master ,配置信息是 FF89X1JK。
  • 节点M:我这里有一些关于我最近收到的其他节点的信息 ,A 节点回复了我的 PING 消息,我认为 A 节点是正常的。B 没有回应我的消息,我猜它现在可能出问题了,但是我需要一些 ACK(Acknowledgement) 消息来确认。
  • 节点N:我也想给你分享一些关于其它节点的信息,C 和 D 节点在指定的时间内回应了我, 我认为它们都是正常的,但是 B也没有回应我,我觉得它现在可能已经挂掉了。
  • 每个节点会向集群中的其他节点发送节点状态信息,如果某个节点挂掉停止了服务,那么会执行投票容错机制,关于这个机制,会在下面讲到。

四、 数据分布理论

现在有一个全量的数据,但是一个机器已经不能满足存储这么多数据了。所以现在考虑分区

Redis(九)--Redis集群
现在有两种分区方式:顺序分区和哈希分区

Redis(九)--Redis集群
Redis(九)--Redis集群
4.1 节点取余分区:

Redis(九)--Redis集群
4.2 一致性哈希分区

Redis(九)--Redis集群

五、Hash 槽

Redis(九)--Redis集群
Redis 集群不使用一致的散列,而是一种不同的分片形式,其中每个键在概念上都是我们称之为散列槽的一部分,目的是使数据均匀的存储在诸多节点中。这点类似于 HashMap 中的桶(bucket)。

Redis 集群中有 16384 个散列槽,为了计算给定**的散列槽,Redis 对 key 采用 CRC16 算法,以下是负责将键映射到槽的算法:

slot = crc16(key) mod NUMER_SLOTS

例如,你可能有3个节点,其中一个集群:

节点 A 包含从0到5500的散列槽。
节点 B 包含从 5501 到 11000 的散列槽。
节点 C 包含 从11001 到16383 的散列槽。

Hash 槽可以轻松地添加和删除集群中的节点。例如,如果我想添加一个新节点 D,我需要将节点 A,B,C 中的一些散列槽移动到 D。同样,如果我想从节点 A 中删除节点 A,可以只移动由 A 服务的散列槽到 B 和 C。当节点 A 为空时,可以将它从群集中彻底删除

六、容错

Redis(九)--Redis集群

  • 集群中的节点不断的 PING 其他的节点,当一个节点向另一个节点发送 PING 命令, 但是目标节点未能在给定的时限内回复,那么发送命令的节点会将目标节点标记为 PFAIL(possible failure,可能已失效)。
  • 当节点接收到其他节点发来的信息时(因为节点之间会通过ping-pong机制来进行通信,节点之间会告诉对方自己的得到的一些其他节点的信息,比如说正常或不正常,所以一个节点会与多个节点进行通讯,会收到很多关于其他节点的信息), 它会记下那些被其他节点标记为失效的节点。 这被称为失效报告(failure report)。
  • 如果节点已经将某个节点标记为 PFAIL , 并且根据节点所收到的失效报告显式, 集群中的大部分其他主节点也认为那个节点进入了失效状态, 那么节点会将那个失效节点的状态标记为 FAIL
  • 一旦某个节点被标记为 FAIL , 关于这个节点已失效的信息就会被广播到整个集群所有接收到这条信息的节点都会将失效节点标记为 FAIL

简单来说, 一个节点要将另一个节点标记为失效, 必须先询问其他节点的意见, 并且得到大部分主节点的同意才行

  • 如果被标记为 FAIL 的是从节点, 那么当这个节点重新上线时, FAIL 标记就会被移除一个从节点是否处于 FAIL 状态,决定了这个从节点在有需要时能否被提升为主节点
  • 如果一个主节点被打上 FAIL 标记之后, 经过了节点超时时限的四倍时间, 再加上十秒钟之后, 针对这个主节点的槽的故障转移操作仍未完成,并且这个主节点已经重新上线的话, 那么移除对这个节点的 FAIL 标记。在不符合上面的条件后,一旦某个主节点进入 FAIL 状态,如果这个主节点有一个或多个从节点存在, 那么其中一个从节点会被升级为新的主节点, 而其他从节点则会开始对这个新的主节点进行复制

新主的选举:

  • 当从节点发现自己复制的主节点已经下线了,会向集群里面广播一条消息,要求所有有投票权的节点给自己投票(所有负责处理槽的主节点都有投票权)
  • 主节点会向第一个给他发选举信息的从节点回复支持
  • 当支持数量>(N/2+1)的情况下,该从节点当选新的主节点。

什么时候整个集群不可用?

若集群任意master挂掉,且当前master没有slave,集群进fail状态,也可以理解为集群中的slot映射[0~16383]不完整时进入fail状态,若**集群超过半数以上master挂掉,无论是否有slave,集群进去fail状态**。

七、Redis Cluster安装——原生安装

有两种安装方法:

  • 原生命令的安装
  • 官方工具安装

7.1 理解架构

Redis(九)--Redis集群

  • 【步骤一】首先配置和开启节点

Redis(九)--Redis集群
rediss服务器在启动的时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式。

Redis(九)--Redis集群
这个时候这些节点都是相互独立的,还不能够相互通信。如果想要相互通信,就需要meet。

  • 【步骤二】meet
    Redis(九)--Redis集群
    Redis(九)--Redis集群
    cluster-node-timeout 15000 :故障转移的时间(节点超时的时间):15秒

  • 【步骤三】分配槽

Redis(九)--Redis集群

  • 【步骤四】设置主从
    Redis(九)--Redis集群
    我们设置了三主三从。

7.2 原生安装——准备节点

首先要在conf文件夹下,配置redis-7000.conf

Redis(九)--Redis集群
Redis(九)--Redis集群
下面我们就可以启动节点了。

启动节点成功后,验证一下节点是否启动成功

Redis(九)--Redis集群
成功启动之后,我们使用客户端连接redis的cluster。

Redis(九)--Redis集群
设置完节点之后,还需要设置槽和设置meet。

Redis(九)--Redis集群
我们可以使用这两个命令来查看集群的信息。

7.2 原生安装——节点握手 即meet操作

Redis(九)--Redis集群
Redis(九)--Redis集群
然后我们让7000和7002meet,然后再对7001节点查看,可以看到他和7000和7002都能连接上。因为可以通过7000进行消息传递。

然后通过这个方法让7000和7001、7002、7003、7004、7005都握手之后,他们彼此之间都能知道彼此的存在。

Redis(九)--Redis集群
7.3 原生安装——分配槽

因为有很多机器,所以不能一个机器一个机器的分配槽,所以我们在/redis/下面新创建一个文件夹 script,然后在 script文件夹下创建一个脚本 addslots.sh。在脚本中写分配槽的操作。

Redis(九)--Redis集群
7.3 原生安装——分配主从

Redis(九)--Redis集群
要cluster replicate 主节点的 id号。

Redis(九)--Redis集群
这样主从节点就分配完了,可以看到主从节点的状态。

八、 扩容集群

Redis(九)--Redis集群

  • 【第一步】首先准备新节点

Redis(九)--Redis集群

  • 【第二步】加入集群

Redis(九)--Redis集群
通过向节点A发送cluster meet命令,客户端可以让接收命令的节点A将另一个节点B添加到节点A所在的集群里面。

Redis(九)--Redis集群
Redis(九)--Redis集群
Redis(九)--Redis集群

  • 【第三步】偏移槽和迁移数据

Redis(九)--Redis集群
每个原来的节点的槽分配一些槽给新进来的节点,上图中就是6379、6380和6381节点槽数据迁移一部分到6385中

Redis(九)--Redis集群
Redis(九)--Redis集群

  • 【第四步】添加从节点

九、在集群中执行命令:

在对数据库中的16384个槽都进行了指派,集群就会进入上线状态,这时候客户端可以向集群中的节点发送数据命令了。

当客户端向节点发送与数据库键有关的命令时,接收命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查和这个槽是否指派给了自己:

  • 如果键所在的槽正好就指派给了当前节点,那么节点直接执行这个命令
  • 如果键所在的槽并没有指派给当前节点,那么节点会向客户端返回一个moved错误,指引客户端转向至正确的节点,并再次发送之前想要执行的命令。

9.1 计算键属于哪个槽?

节点使用以下算法来计算给定键key属于哪个槽:

def slot_number(key):
	return CRC16(key)&16383

使用CLUSTER KEYSLOT命令查看一个给定键属于哪个槽

9.2 判断槽是否由当前节点负责处理

当节点计算出键所属的槽i之后,节点就会检查自己在clusterState.slots数组中的项i,判断键所在的槽是否由自己负责:

  • 1),如果clusterState.slots[i]等于clusterState.myself,那么说明槽i由当前节点负责,节点可以执行客户端发送命令。
  • 2),如果clusterState.slots[i]不等于clusterState.slots.myself,那么说明槽i并非由当前节点负责,节点会根据clusterState.slots[i]指向的clusterNode结构所记录的节点IP和端口号,向客户端返回moved错误,指引客户端转向至正在处理槽i的节点。

9.3.moved错误:

当节点发现键所在的槽并非由自己负责处理的时候,节点就会向客户端返回一个moved错误,指引客户端转向至正在负责槽的节点。

moved错误的格式为:

MOVED <slot><ip>:<port>

十、收缩集群

Redis(九)--Redis集群
10.1 下线迁移槽

Redis(九)--Redis集群
就是下线节点的槽迁移到其他节点上

10.2 忘记节点

Redis(九)--Redis集群

十一、重新分片:

redis集群的重新分片操作可以将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所属的键值对也会从源节点被移动到目标节点

Redis(九)--Redis集群

十二、客户端路由

Redis(九)--Redis集群
12.1 moved 重定向

Redis(九)--Redis集群
Redis(九)--Redis集群
Redis(九)--Redis集群
Redis(九)--Redis集群
Redis(九)--Redis集群
当使用-c之后是告诉他使用集群模式,所以如果插入的数据槽不命中,他会自动转化到对应的槽的节点上,当执行完上述命令行后,会自动跳转到转换的节点上

Redis(九)--Redis集群
这句命令行来查看 hello 可以被分配到哪个槽上。

12.2 ASK重定向

Redis(九)--Redis集群
Redis(九)--Redis集群
Redis(九)--Redis集群
ASK和MOVED错误都会导致客户端额转向,他们的区别是:

  • MOVED错误代表槽的负责权已经从一个节点转移到另一个节点:在客户端收到关于槽i的MOVED错误之后,客户端每次遇到关于槽 i的命令请求时,都可以直接将命令请求发送至MOVED错误所指向的节点,因为该节点就是目前负责槽i的节点
  • 于此相反,ASK错误只是两个节点在迁移槽的过程中使用的一种临时措施:在客户端收到关于本槽i的ASK错误之后,客户端只会在接下来的一次命令请求中将关于槽i的命令请求发送至ASK错误所指示的节点,但这种转向不会对客户端今后发送关于槽i的命令产生任何影响,客户端仍然会将关于槽i的命令请求发送至目前负责处理槽i的节点,除非ASK错误再次出现

十三、故障转移:

当一个从节点发现自己正在复制的主节点进入了已经下线状态时,从节点将开始对下线主节点进行故障转移,以下是故障转移的执行步骤:

  • 1)复制下线主节点的所有从节点里面,会有一个从节点被选中
  • 2)被选中的从节点会执行slaveof no one命令,成为新的主节点
  • 3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己
  • 4)新的主节点像集群广播一条pong消息,这条pong消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽
  • 5)新的主节点开始接收和自己负责处理的槽有关命令请求,故障转移完成

补充:几道题:

1,redis-cluster集群的特点:

  • 所有的redis节点彼此关联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽
  • 节点的fail是通过集群中超过半数的节点检测失效时才生效
  • 客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群的所有节点,连接集群中任何一个可用节点即可
  • redis-cluster把所有的物理节点映射到[0~16383]slot上(不一定是平均分配的),cluster负责维护
  • redis集群预分配好16384个哈希槽,当需要在redis集群中放置一个key-value时,redis先对key使用CRC16算法算出一个结果,然后把结果对16383求余数,这样每个key都会对应一个编号在1~16383之间的哈希槽,redis会根据节点数量大致均等的哈希槽映射到不同的节点

2,为什么使用redis-cluster?

  • 为了在大流量访问下提供稳定的业务,集群化是存储的必然形态
  • 未来发展趋势肯定格式云计算和大数据的紧密结合
  • 只有分布式架构能满足要求

3,数据分片模型

为了解决读写分离模型的缺陷(缺陷为:不管是master还是slave,每个节点都必须保存完整的数据,若在数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力

==>为了解决读写分离模型的缺陷,可以将数据分片模型应用进来,可以将每个节点看成都是独立的master,然后通过业务实现数据分片(可以将每个master设计成由一个master和多个slave组成的模型)

4,redis集群有哪几种形式(原理及优缺点)

==>主要有主从复制,哨兵模式,redis-cluster

这里只写了优缺点,其对应的原理看相应的笔记。

1),主从复制:

优点:

  • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
  • 为了分载master的读操作的压力,slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由master来完成
  • slave同样可以接受其他slave的链接和同步请求,这样就 可以有效的分载master压力
  • master-slave是以非阻塞的方式为slave提供服务,所以在master-slave同步期间,客户端仍然可以提交查询或修改请求
  • slave-server同样以非阻塞的方式完成数据同步。在同步期间,若有客户端提交查询请求,redis则返回同步之前的数据

缺点:

  • redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写分离请求失败,需要等待机器重启或手动切换前端的ip才能恢复
  • 主机宕机,宕机之前有部分数据未能及时同步到 从机,切换ip之后还会引入数据不一致的问题,降低了系统的可用性
  • redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得复杂。

2)哨兵模式:

优点:

  • 哨兵模式是基于主从模式的,所有主从模式的有点哨兵模式都有
  • 哨兵可以自动切换,系统更加健壮,可用性更高

缺点:

  • redis较难支持在线扩容,在集群容量达到上限时在线扩容会变的很fuza

3)redis-cluster:

优点:

  • 将数据自动切分(split)到多个节点的能力。
  • 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
  • 支持动态扩容

缺点:

  • 键的批量操作支持有限,比如mset, mget,如果多个键映射在不同的槽,就不支持了
  • 键事务支持有限,当多个key分布在不同节点时无法使用事务,同一节点是支持事务
  • 键是数据分区的最小粒度,不能将一个很大的键值对映射到不同的节点 d,不支持多数据库,只有0,select 0
  • 复制结构只支持单层结构,不支持树型结构。

5,是否使用过redis集群,集群的原理是什么?

这个题目其实和上面一道题的实质是一样的。

  • redis sentinel着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务
  • redis-cluster着眼于扩展性,在单个redis内存 不足时,使用cluster进行分片存储。

6,什么时候整个集群不可用?

若集群任意master挂掉,且当前master没有slave,集群进fail状态,也可以理解为集群中的slot映射[0~16383]不完整时进入fail状态,若**集群超过半数以上master挂掉,无论是否有slave,集群进去fail状态**。

7,哨兵模式和集群模式的区别?

  • 哨兵模式监督权交给了哨兵系统,集群模式中是工作节点自己做监督
  • 哨兵模式发起选举时选举一个leader哨兵节点来处理故障转移,集群模式是在从节点中选举出一个新的主节点,来处理故障转移

感谢并参考:

https://blog.csdn.net/xiaojie_570/article/details/86530949

https://blog.csdn.net/my13413527259/article/details/85062976?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase

相关标签: Redis