写点什么

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

评论 2 条评论

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

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

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

使用HTTP工作的Web服务器

穿过生命散发芬芳

web服务器 12月月更

软件设计中最关键的“开闭原则”,究竟指什么呢?

JAVA旭阳

架构 后端

【12.16-12.23】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动

Java本地高性能缓存实践

阿里技术

cache 本地缓存 缓存Java

贾斯特里尼&布鲁克斯葡萄酒,贵族品质值得选择

联营汇聚

Dubbo架构设计与源码解析(三)责任链模式

京东科技开发者

dubbo 过滤器 filter 责任链 provider

搭建"积木"=编程?

间隔

AI技术实践|用腾讯云智能文本图像增强打造一个掌上扫描仪

牵着蜗牛去散步

人工智能 腾讯云 文字识别 图像处理

WorkPlus助力中交四航局打造数字化管理新模式,释放企业生产力

WorkPlus

火山引擎DataTester上线“流程画布”功能,支持组合型A/B实验分析

字节跳动数据平台

大数据 AB testing实战 12 月 PK 榜

你的企业IM安全吗?对于私有化的即时通讯软件你了解多少?

WorkPlus

跨平台应用开发进阶(四十二)vue与nvue页面设计方案探究

No Silver Bullet

uni-app Vue 12月月更 nvue

Team Lead 的日常工作

QE_LAB

敏捷团队

阿里灵杰:与开发者一起推动AI创新落地

阿里云大数据AI技术

人工智能 阿里云 开发者 AI技术

BitSail issue持续更新中,快来挑战,赢取千元礼品!

字节跳动数据平台

大数据 开源 12 月 PK 榜

扬州万方:基于申威平台的 Curve 块存储在高性能和超融合场景下的实践

网易数帆

nvme 分布式存储 curve 12 月 PK 榜

JavaScript基础:在Jupyter Notebook中操练

无人之路

JavaScript Jupyter Notebook

想在“互联网信息高速公路”顺畅通行,华为云CDN来助力

秃头也爱科技

企业IM软件WorkPlus,组织高效协作与一体化办公首选

WorkPlus

阿里巴巴最新出版的 Java 面试参考指南(泰山版)开源了!

架构师之道

编程 程序员 java面试

极速畅享网络体验,华为云CDN加速一通到底

秃头也爱科技

华为云大数据BI,赋能数字化企业加速发展

秃头也爱科技

跨平台应用开发进阶(三十八)uni-app前端监控方案:基调听云APP探究

No Silver Bullet

uni-app 前端监控 12月月更 基调听云APP

敏捷价值流管理

敏捷开发

敏捷 敏捷开发 价值流 价值流管理

【Go实现】实践GoF的23种设计模式:命令模式

元闰子

Go 设计模式 命令模式

JavaScript进阶(十三)JavaScript 空值合并运算符、可选链操作符、空值赋值运算符讲解

No Silver Bullet

JavaScript 12月月更 空值合并运算符 可选链操作符 空值赋值运算符讲解

金融科技 DevOps 的最佳实践

SEAL安全

DevOps 最佳实践 FinTech 12 月 PK 榜

如何保证设计出合理的架构1-4

程序员小张

「架构实战营」

提升游戏玩家体验,华为云CDN加速了解一下

秃头也爱科技

中移链已在BSN-DDC基础网络上线元交易功能

BSN研习社

BSN-DDC

【重磅干货】如何构建 API 生态促进企业上下游合作

石臻臻的杂货铺

API

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