AICon上海|与字节、阿里、腾讯等企业共同探索Agent 时代的落地应用 了解详情
写点什么

Redis Cluster 原理初探

  • 2019-09-20
  • 本文字数:3405 字

    阅读完需:约 11 分钟

Redis Cluster原理初探

虽然到现在仍未发现公司内部有团队在使用 Redis Cluster,但是这丝毫不影响我们去了解它。Redis Cluster 是一个可以在多个 Redis 节点之间进行数据共享的分布式集群。和以往了解的客户端通过一致性哈希解决 redis 多节点负载均衡的方式不同,Redis Cluster 是在服务端,通过节点之间的特殊协议进行通讯,达到服务端对请求进行负载均衡。对于客户端来说,其负载均衡策略是透明的,客户端不需要自己做负载均衡。

集成简介

Redis Cluster 特性之一是引入了槽的概念。一个 redis 集群包含 16384 个哈希槽,集群中的每个 redis 节点,分配到一部分槽。而集群使用公式 CRC16(key) % 16384 来计算每次请求的键 key 属于哪个槽,通过查询集群配置,便可知道 key 对应的槽属于哪个 redis 节点,然后再将请求打到该节点。举个例子,一个集群可以有两个节点,其中:


1.节点 A 负责处理 0 号至 5000 号哈希槽。


2.节点 B 负责处理 5001 号至 10000 号哈希槽。


3.节点 C 负责处理 10001 号至 16383 号哈希槽。


通过上述公式,可对 key X 计算出一个值,该值为 0-16383 中的一个数。假设 key X 通过上述公式计算出来的值为 34,根据上面例子,34 即为槽标识,亦 key X 属于槽 34,而槽 34 分配到了节点 A,也就是说节点 A 负责 key X 的读写。


通过将哈希槽分布到不同节点,我们可以很容易地向集群中添加或者删除节点。比如说:


  1. 如果用户将新节点 D 添加到集群中,那么集群只需要将节点 A 、B、C 中的某些槽移动到节点 D 就可以了。

  2. 与此类似,如果用户要从集群中移除节点 A ,那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C ,然后再移除节点 A 就可以了。


因为槽在节点之间移动不会造成节点阻塞,所以无论是添加新节点还是移除已存在节点,又或者改变某个节点包含的哈希槽数量,都不会造成集群下线,redis 集群能保证槽的平滑移动。


RedisCluster 还有一个特性便是去中心化。客户端可以连接集群中的任意一个节点,集群中的任意一个节点都可对外提供服务。节点之间可共享集群配置(如槽的分配)。或者我们可以理解为,集群中的任意一个节点都是中心节点。假设有两个节点 A 和 B,客户端连接了 A 节点,并发起了一次请求 a,A 节点计算请求 a 的 key 得知该请求应该打到 B 节点上,然后 A 节点对请求 a 返回一个 MOVED B,通知客户端重定向到 B 节点。

集成简介

redis 集群架构图


因为槽在节点之间移动不会造成节点阻塞,所以无论是添加新节点还是移除已存在节点,又或者改变某个节点包含的哈希槽数量,都不会造成集群下线,redis 集群能保证槽的平滑移动。


以上图片,蓝色的为 redis 节点,这里是指 master 节点,一个 master 节点可以配置多个 slave。绿色为客户端,可以理解为我们的应用。


架构细节:


(1)所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。


(2)节点的 fail 是通过集群中超过半数的节点检测失效或者某个节点主从全挂时才生效。


(3)客户端与 redis 节点直连,不需要中间 proxy 层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。


(4)redis-cluster 把所有的物理节点映射到[0-16383]slot 上。

集群容错

为了当部分节点失效时,cluster 仍能保持可用,Redis 集群采用每个节点拥有 1(主服务自身)到 N 个副本的主从模型。类似于 master/slave。但是 redis cluster 却不是强一致性的,因为 cluster 内部 master 和 slave 之间是通过异步复制做数据同步的,复制过程中可能 master 挂了,这就导致部分数据没有完全同步至 slave 上,不过这种可能性还是很小的。


以上是集群选举过程。


选举过程是集群中所有 master 参与,如果半数以上 master 节点与当前 master 节点通信超时,则集群认为当前 master 节点挂掉.


什么时候整个集群不可用?当集群不可用时, 所有对集群的操作做都将失败。以下是会导致集群不可用的其中两种情况:


a:集群任意 master 挂掉,并且当前 master 没有 slave,集群不可用。


b:集群超过半数以上 master 挂掉,无论是否有 slave,集群不可用。

集群扩展

什么时候整个集群不可用?当集群不可用时, 所有对集群的操作做都将失败。以下是会导致集群不可用的其中两种情况:


选举过程是集群中所有 master 参与,如果半数以上 master 节点与当前 master 节点通信超时,则集群认为当前 master 节点挂掉。


以往的一致性哈希方案,如果我们移除或者新增节点时,虽然说不会导致全局 key 的 rehash,但是也会影响到部分 key 的失效。Redis Cluster 在可用性和可扩展性上比较重视,如果集群新增一个节点,在给该节点分配槽时,这些槽所属的源节点和该节点会进行一次 key 的迁移,并且迁移过程中不阻塞集群服务。如果移除一个节点,同理,我们需要将待移除的节点的 key 迁移到另一个节点上。


那集群是如何做到 key 迁移不阻塞集群服务的呢?


key 迁移过程中,涉及到 CLUSTER SETSLOT slot8 MIGRATING node 命令和 CLUSTER SETSLOT slot8 IMPORTING node 命令,前者用于将给定节点 node 中的槽 slot8 迁移出节点,而后者用于将给定槽 slot8 导入到节点 node :


(1)、如果一个槽被设置为 MIGRATING 状态时,原本持有该槽的节点会继续接受关于这个槽的命令请求,但只有当键存在于该节点时,节点才会处理这个请求。如果命令所使用的键不存在于该节点,那么节点将向客户端返回一个 ASK 转向(redirection)错误,告知客户端,要将命令请求发送到槽的迁移目标节点。


(2)、如果一个槽被设置为 IMPORTING 状态时,节点仅在接收到 ASKING 命令之后,才会接受关于这个槽的命令请求。如果客户端向节点发送该槽的数据请求,命令为非 ASKING 时,那么节点会使用 MOVED 转向错误将命令请求转向至真正负责处理这个槽的节点。


举个例子来看看。


假设现在,我们有 A 和 B 两个节点,我们想将槽 8 从节点 A 移动到节点 B ,于是我们:


**(1)、向节点 B 发送命令 CLUSTER SETSLOT 8 IMPORTING A


(2)、向节点 A 发送命令 CLUSTER SETSLOT 8 MIGRATING B**


每当客户端向其他节点发送关于哈希槽 8 的命令请求时,这些节点都会向客户端返回指向节点 A 的转向信息(迁移中,虽然 A 和 B 都有槽 8 所对应的 key,但是各个节点仍然认为槽 8 由 A 负责,只有迁移结束后,槽 8 才属于 B 节点而不属于 A)。


(1)、如果命令要处理的键已经存在于槽 8 里面,那么这个命令将由节点 A 处理。



(2)、如果命令要处理的键未存在于槽 8 里面,那么这个命令由节点 B 处理。



这种机制将使得节点 A 不再创建关于槽 8 的任何新键。


与此同时,一个特殊的客户端 redis-trib 以及 Redis 集群配置程序(configuration utility)会将节点 A 中槽 8 里面的键移动到节点 B 。移动 key 的操作是原子性的,也就是一个 key 如果从 A 移动到 B,那么移动时,都不会出现 key 在 A 和 B 中同时出现。

内部数据结构

RedisCluster 涉及三个核心的数据结构 clusterState、clusterNode、clusterLink 都在 cluster.h 中定义。这三个数据结构中最重要的属性就是:clusterState.slots、clusterState.slots_to_keys 和 clusterNode.slots,它们保存了三种映射关系:


clusterState:集群状态


nodes:所有结点


migrating_slots_to:迁出中的槽


importing_slots_from:导入中的槽


slots_to_keys:槽中包含的所有 Key,用于迁移 Slot 时获得其包含的 Key


slots:Slot 所属的结点,用于处理请求时判断 Key 所在 Slot 是否自己负责 clusterNode:结点信息


slots:结点负责的所有 Slot,用于发送 Gossip 消息通知其他结点自己负责的 Slot。


clusterLink:与其他结点通信的连接


以下为这三个数据结构的定义:






结合以上数据结构,我们看看客户端请求集群时,集群处理的的流程:


1、检查 key 所在 Slot 是否属于当前节点?


  • 1.1 计算 crc16(key) % 16384 得到 Slot

  • 1.2 查询 clusterState.slots 负责 Slot 的结点指针

  • 1.3 与 myself 指针比较


2、若不属于,则响应 MOVED 错误重定向客户端


3、若属于且 Key 存在,则直接操作,返回结果给客户端


4、若 Key 不存在,检查该 Slot 是否迁出中?(clusterState.migrating_slots_to)


5、若 Slot 迁出中,返回 ASK 错误重定向客户端到迁移的目的服务器上


6、若 Slot 未迁出,检查 Slot 是否导入中?(clusterState.importing_slots_from)


7、若 Slot 导入中且请求有 ASKING 标记,则直接操作


8、否则响应 MOVED 错误重定向客户端


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/zjwiOkRFvQDpKfeFL1-dUQ


2019-09-20 14:228775

评论 2 条评论

发布
用户头像
若客户端连接的master 节点挂了,是如何处理的呢?

客户端与 redis 节点直连,不需要中间 proxy 层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

2021-02-25 12:00
回复
集群下,一般客户端不会配置链接一个节点。如果链接的节点都挂了,那就没办法了
2023-09-16 10:28 · 福建
回复
没有更多了
发现更多内容

第二节:SpingBoot单元测试

入门小站

java 编程

打造智能全场景,《HarmonyOS Connect系列课》7大BUFF为您助力!

HarmonyOS开发者

用户文章转载:Windows用户都来看看,这个锅P4不背

龙智—DevSecOps解决方案

perforce P4

AJAX工作原理及其优缺点

编程江湖

深入解析Apache Pulsar系列: Broker消息确认的管理

博文视点Broadview

crontab介绍安装及每秒运行

Owen Zhang

Linux crontab

Bruce Eckel教你如何爬出 Gradle 的“坑”?

图灵社区

java 编程

vivo 推送平台架构演进

vivo互联网技术

分布式 架构设计 消息推送 平台搭建、

前端开发之Vue事件修饰符和按键修饰符

@零度

Vue 前端开发

热烈庆祝龙智高级咨询顾问叶燕秀获得“Atlassian认证专家”称号

龙智—DevSecOps解决方案

Atlassian认证专家 Atlassian认证

复盘和反思一个被全公司邮件通报的漏测

LynnYang

测试 Postman Mock

LeetCode 每日一题 No.1220 统计元音字母序列的数目

DawnMagnet

rust LeetCode 力扣

当类的泛型相关时,如何在两个泛型类之间创建类似子类型的关系

阿Q说代码

Java泛型 1月月更 子类型

高效时代,是时候过渡到自动化测试了

飞算JavaAI开发助手

DevOps 软件开发 自动测试

Apache Kylin PMC 马洪宾:开源,就是一场“螺旋上升”的旅程

腾源会

60岁代码匠的几篇小作文,解决了大多数程序的迷茫(下)

图灵社区

java 编程

60岁代码匠的几篇小作文,解决了大多数程序的迷茫(上)

图灵社区

java 编程

这8个JS 新功能,你应该去尝试一下

华为云开发者联盟

JavaScript 前端 开发 索引 开发语言

2022年RPA行业发展十大趋势,六千字长文助你看懂RPA

王吉伟频道

RPA 机器人流程自动化 RPAaaS 超自动化 自动化优先

Linux下玩转nginx系列(一)——初识nginx及其使用入门

anyRTC开发者

nginx Linux 音视频 WebRTC 服务器

利用物联网技术加速数字化转型

龙智—DevSecOps解决方案

龙智搬迁公告

龙智—DevSecOps解决方案

搬迁

hi 龙蜥小二来了 ,一键@为你答疑解惑

OpenAnolis小助手

Linux 服务

深入分析JUC之Lock接口

编程江湖

lock锁

云图说|图解DGC:基于华为智能数据湖解决方案的一体化数据治理平台

华为云开发者联盟

大数据 数据湖 数据治理 数据服务 数据湖治理中心

Flink,Spark,Storm,Hadoop框架比较

@零度

flink hadoop spark Storm 大数据开发

全面提升体系化数据管理能力 | OceanBase 发布全新3.X工具家族

OceanBase 数据库

数据库 开源 开发者 OceanBase 社区版 产品发布

Flink是如何支持批流一体的

编程江湖

flink

几行代码,把zip文件直接破解

你?

都2022年了,你的前端工具集应该有vueuse

华为云开发者联盟

Vue 前端 API 工具集 vueuse

java开发之Redis数据结构

@零度

redis JAVA开发

Redis Cluster原理初探_文化 & 方法_邱润景_InfoQ精选文章