redis--18--集群--理论

redis–18–集群–理论

1、集群简介

1.1、主从架构

在这里插入图片描述

优点

读写分离,通过增加Slaver可以提高并发读的能力。

缺点

Master写能力是瓶颈。

1.2、哈希Slot

在这里插入图片描述

  1. 对象保存到Redis之前先经过CRC16哈希到一个指定的Node上,例如Object4最终Hash到了Node1上。
  2. 将整个数据库分为16384个槽位,所有Key的数据都是这些slot的一个,每个Node被平均分配了一个Slot段,对应着0-16384,Slot不能重复也不能缺失,否则会导致对象重复存储或无法存储。
  3. Node之间也互相监听,一旦有Node退出或者加入,会按照Slot为单位做数据的迁移。例如Node1如果掉线了,0-5640这些Slot将会平均分摊到Node2和Node3上,由于Node2和Node3本身维护的Slot还会在自己身上不会被重新分配,所以迁移过程中不会影响到5641-16384 Slot段的使用。
缺点

每个Node承担着互相监听、高并发数据写入、高并发数据读出,工作任务繁重

优点:

将Redis的写操作分摊到了多个节点上,提高写的并发能力,扩容简单。

1.3、集群

主从和哈希的设计优缺点正好是相互弥补的,将图1每一套主从对应到图2中的每一个Node,就是Redis集群的终极形态,先Hash分逻辑节点,然后每个逻辑节点内部是主从,如下图

在这里插入图片描述

  1. 想扩展并发读就添加Slaver
  2. 想扩展并发写就添加Master
  3. 想扩容也就是添加Master
  4. 任何一个Slaver或者几个Master挂了都不会是灾难性的故障。

1.3.1、总结

  1. Redis集群是一个由多个节点(至少6个)组成的分布式服务集群,它具有复制、高可用和分片特性
    1. 主节点:分配槽,处理客户端的命令请求
    2. 从节点:可用在主节点故障后,顶替主节点
  2. Redis的集群没有中心节点,并且带有复制和故障转移特性,这可用避免单个节点成为性能瓶颈,或者因为某个节点下线而导致整个集群下线
  3. Master既是主节点又是哨兵,可以实现高可用
  4. Redis集群将整个数据库分为16384个槽,数据库中的每个键都属于16384个槽中的其中一个
  5. 集群中的每个主节点都可以负责0个至16384个槽,当16384个槽都有节点在负责时,集群进入上线状态,可以执行客户端发送的数据命令
  6. 主节点只会执行和自己负责的槽有关的命令,当节点接收到不属于自己处理的槽的命令时,它将会处理指定槽的节点的地址返回给客户端,而客户端会向正确的节点重新发送
  7. 如果需要完整地分片、复制和高可用特性,并且要避免使用代理带来的性能瓶颈和资源消耗,那么可以选择使用Redis集群
  8. 如果只需要一部分特性(比如只需要分片,但不需要复制和高可用等),那么单独选用twemproxy,Redis的复制和Redis Sentinel中的一个或多个
twemproxy

twemproxy是位于客户端和服务器之间的路由代理层,计算方式是:key%服务器数量

twemproxy产生的三个问题:

  1. 单点故障(不能实现高可用)
  2. 数据倾斜(特殊K值,大部分数据放置在某一台服务器上)
  3. 数据摘取(新服务器加入时整个数据做全量再分发)

1.3.2、原理图

在这里插入图片描述

1.3.3、原理图说明

  1. 该集群包含 6 个 Redis 节点,3主3从,分别为M1,M2,M3,S1,S2,S3。
  2. 主从 Redis 节点 会进行数据复制(同步)
  3. 所有 Redis 节点 采用 Gossip 协议进行通信,交换维护节点元数据信息。
  4. 主节点:一般 处理 读写操作
  5. 从节点:一般 只处理 读操作。

2、redis数据分片策略

在这里插入图片描述

  1. Redis Cluster 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内,计算公式如下
slot = CRC16(key) & 16383。
  1. 每一个节点负责维护一部分槽以及槽所映射的键值数据。

2.1、虚拟哈希槽分区的特点

  1. 解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
  2. 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据
  3. 支持节点、槽和键之间的映射查询,用于数据路由,在线集群伸缩等场景。
  4. 槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动。

3、集群伸缩的原理

3.1、扩容集群

3.1.1、案例

我们通过 Redis Cluster 的命令来模拟整个过程。

在这里插入图片描述

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

3.1.2、案例说明

1. 首先启动一个 Redis 节点,记为 M4。
2. 使用 cluster meet 命令,让新节点(M4)加入到集群中。新节点(M4)刚开始都是主节点状态,由于没有负责的槽,所以不能接受任何读写操作,后续我们就给他迁移槽和填充数据。
3. 对 M4 节点发送 cluster setslot { slot } importing { sourceNodeId } 命令,让目标节点准备导入槽的数据。
4. 对源节点,也就是 M1,M2,M3 节点发送 cluster setslot { slot } migrating { targetNodeId } 命令,让源节点准备迁出槽的数据。
5. 源节点执行 cluster getkeysinslot { slot } { count } 命令,获取 count 个属于槽 { slot } 的键,然后执行步骤六的操作进行迁移键值数据。
6. 在源节点上执行 migrate { targetNodeIp} " " 0 { timeout } keys { key... } 命令,把获取的键通过 pipeline 机制,批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
7. 重复执行步骤5和步骤6,直到槽下所有的键值数据迁移到目标节点(M4)。
8. 向集群内所有主节点发送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配给目标节点(M4)。为了保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽执行新节点(M4)。

3.2、收缩集群

收缩节点就是将 Redis 节点下线,整个流程需要如下操作流程。

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

3.2.1、案例

下线节点需要将节点自己负责的槽迁移到其他节点,原理与之前节点扩容的迁移槽过程一致。

在这里插入图片描述

迁移完槽后,还需要通知集群内所有节点忘记下线的节点,也就是说让其他节点不再与要下线的节点进行 Gossip 消息交换。

Redis 集群使用 cluster forget { downNodeId } 命令,将指定的节点加入到禁用列表中,在禁用列表内的节点不再发送 Gossip 消息。

4、客户端路由

在集群模式下,Redis 节点接收任何键相关命令时首先计算键对应的槽,在根据槽找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点。这个过程称为 MOVED 重定向。

需要注意的是 Redis 计算槽时并非只简单的计算键值内容,当键值内容包括大括号时,则只计算括号内的内容。比如说,key 为 user:{10000}:books时,计算哈希值只计算10000。

MOVED 错误示例显示的信息如下

键 x 所属的哈希槽 3999 ,以及负责处理这个槽的节点的 IP 和端口号 127.0.0.1:6381 。 

客户端需要根据这个 IP 和端口号, 向所属的节点重新发送一次 GET 命令请求。

由于请求重定向会增加 IO 开销,这不是 Redis 集群高效的使用方式,而是要使用 Smart 集群客户端。Smart 客户端通过在内部维护 slot 到 Redis 节点的映射关系,本地就可以实现键到节点的查找,从而保证 IO 效率的最大化,而 MOVED 重定向负责协助客户端更新映射关系。

Redis 集群支持在线迁移槽(slot)和数据来完成水平伸缩,当 slot 对应的数据从源节点到目标节点迁移过程中,客户端需要做到智能迁移,保证键命令可正常执行。例如: 当 slot 数据从源节点迁移到目标节点时,期间可能出现一部分数据在源节点,而另一部分在目标节点。

4.1、客户端命令执行流程

在这里插入图片描述

  1. 客户端根据本地 slot 缓存发送命令到源节点,如果存在键对应则直接执行并返回结果给客户端。

  2. 如果节点返回 MOVED 错误,更新本地的 slot 到 Redis 节点的映射关系,然后重新发起请求。

  3. 如果数据正在迁移中,节点会回复 ASK 重定向异常。格式如下:
    ( error ) ASK { slot } { targetIP } : { targetPort }

    1. 客户端从 ASK 重定向异常提取出目标节点信息,发送 asking 命令到目标节点打开客户端连接标识,再执行键命令。

4.1.1、ASK 和 MOVED 相同点

ASK 和 MOVED 虽然都是对客户端的重定向控制

4.1.2、ASK 和 MOVED 区别

  1. ASK 重定向说明集群正在进行 slot 数据迁移,客户端无法知道什么时候迁移完成,因此只能是临时性的重定向,客户端不会更新 slot 到 Redis 节点的映射缓存。
  2. MOVED 重定向说明键对应的槽已经明确指定到新的节点,因此需要更新 slot 到 Redis 节点的映射缓存。

5、故障转移

当 Redis 集群内少量节点出现故障时通过自动故障转移保证集群可以正常对外提供服务。

当某一个 Redis 节点客观下线时,Redis 集群会从其从节点中通过选主选出一个替代它,从而保证集群的高可用性。

6、Redis集群的功能限制

  1. key批量操作(类似mset、mget操作) 支持有限。
    1. 只支持key映射到一个slot值的批量操作。
    2. 不只支持key映射到多个slot值的批量操作。因为多个slot值就可能多个节点
  2. key事务操作支持有限。
    1. 只支持多key在同一节点上的事务操作
  3. key作为数据分区的最小粒度,不能将一个大的键值对象如 hash、list 等映射到不同的节点。
  4. 不支持多数据库空间
  5. 单机下的Redis可以支持16个数据库(db0 ~ db15),集群模式下只能使用一个数据库空间,即 db0。
  6. 复制结构 只支持一层
  7. 从节点只能复制主节点,不支持嵌套树状复制结构。

7、注意点

默认情况下,当集群 16384 个槽任何一个没有指派到节点时整个集群不可用。执行任何键命令返回 CLUSTERDOWN Hash slot not served 命令。

当持有槽的主节点下线时,从故障发现到自动完成转移期间整个集群是不可用状态,对于大多数业务无法忍受这情况,因此建议将参数 cluster-require-full-coverage 配置为 no ,当主节点故障时只影响它负责槽的相关命令执行,不会影响其他主节点的可用性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值