【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

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:228476

评论 2 条评论

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

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

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

软件测试/测试开发丨Python 常用第三方库 yaml

测试人

Python 程序员 软件测试 测试开发

生成式AI:未来内容产业的变革力量

百度开发者中心

人工智能 百度文心一言

质效提升 | QA不做业务需求测试,你怎么看?

laofo

DevOps cicd 研发效能 持续交付 质量赋能

读《芯片浪潮》,学习台积电张忠谋的管理之道

博文视点Broadview

面部表情识别技术的伦理问题与应对策略

来自四九城儿

SpringBoot有几种获取Request对象的方法?

王磊

java面试

React和Vue的区别,大家怎么看?

FinFish

Vue React 小程序容器 混合app

生成式AI:人工智能新生产力

百度开发者中心

人工智能 百度文心一言

CPU 缓存行

红袖添香

Java 多线程 MESI 缓存行 伪共享

生成式AI助力人工智能下半场

百度开发者中心

人工智能 百度文心一言

SaaS出海:黄粱易得,黄金难收

ToB行业头条

生成式AI发展前景展望:创新、应用与市场规模

百度开发者中心

人工智能 百度文心一言

NLP文本匹配任务Text Matching 有监督训练:PointWise(单塔)、DSSM(双塔)、Sentence BERT(双塔)项目实践

汀丶人工智能

人工智能 自然语言处理 文本匹配

低代码平台轻松玩转业务规则

鲸品堂

低代码 低代码开发 企业号 8 月 PK 榜

RHG之人工智能漏洞挖掘

云起无垠

学习Java 8 Stream,提升编码能力!

互联网工科生

Java stream Java11 Stream API

更方便的集成使用!IoTDB plugin 上线 Grafana 官网!

Apache IoTDB

2023-08-14:用go语言写算法。给出两个长度相同的字符串 str1 和 str2 请你帮忙判断字符串 str1 能不能在 零次 或 多次 转化 后变成字符串 str2 每一次转化时,你可以将

福大大架构师每日一题

福大大架构师每日一题

NLP文本匹配任务Text Matching 有监督训练:PointWise(单塔)、DSSM(双塔)、Sentence BERT(双塔)项目实践

汀丶人工智能

人工智能 自然语言处理 文本匹配算法

使用 Amazon MemoryDB for Redis 作为 JuiceFS 的元数据引擎

亚马逊云科技 (Amazon Web Services)

Amazon

C++11时间日期库chrono的使用

攻城狮Wayne

深度开发者故事 | 华为云API Explorer 自动化运维的得力助手

华为云PaaS服务小智

华为 API 华为云

面部表情识别:心理学与计算机科学的交汇点

来自四九城儿

生成式AI在电信行业的有所为与有所不为

百度开发者中心

人工智能 文心一言

ARTS 打卡第 5 天

自由

ARTS 打卡计划

可行性研究报告编制方案

金陵老街

面部表情识别研究:解读情绪的密码

来自四九城儿

ByConity 首次 TPC-DS 测试结果发布 & 新活动邀请!

字节跳动开源

大数据 开源 字节跳动 数仓 社区

鱼龙混杂的网络营销行业:入行新人如何规划职业

石头IT视角

Go 常量

小万哥

Go 程序员 云原生 后端 开发

【第1讲】Python3.11的下载、安装和卸载,有手就能学会

程序员晚枫

Python 安装 入门

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