Redis深入理解-三次握手、槽位机制

Redis 节点之间的三次握手原理分析

比如多台 Redis 之间要建立集群,那么连接其中的一台 Redis 客户端,向其他 Redis 发送 meet 命令即可通知其他节点,那么发送 meet 命令给其他节点后,对方也会在内存中创建一个 ClusterNode 结构,来维护集群中的节点信息

这里的三次握手指的是 Redis 中的三次握手用来建立应用层的连接(即进行集群节点之间的连接),与 TCP 三次握手不同

那么 Redis 中集群的建立就是通过 三次握手 + Gossip 协议 来实现的

Gossip 协议也被称作是具有代表性的最终一致性的 分布式共识协议,特点就是需要同步的信息如同流言一般进行传播

Gossip 协议具体流程就是,对于需要同步的信息,从信息源节点开始,随机选择连接的 k 个节点来传播消息,每一个节点收到消息后,如果之前没有收到过,就也发送给除了之前节点的相邻的 k 个节点,直到最后整个网络中的所有节点都收到了消息,达到了最终一致性。

基于 slots 槽位机制的数据分片原理

在 Redis 分布式集群中,我们将数据分散的放在了各个 Redis 节点中,这样才可以更好利用分布式集群的优点(增加数据读写速度、分散存储数据的话,增加集群节点也就相当于扩大 Redis 内存),那么如何来组织数据的存放位置呢

并且还存在一个问题,在集群扩容或者缩容时,也就是集群节点增加或者减少,那么就需要进行数据迁移

解释一下为什么要进行数据迁移:如果在集群中新增加一个节点,那么该节点中的数据是空的,那么肯定不合理,因此要将其他节点中的数据转移一部分数据到新的集群节点中去,缩容同理

那么对于 组织数据存放位置 以及 数据迁移 这两个问题是如何解决的呢?

通过 槽位机制 来实现

我们先来了解一下数据分片的概念,数据分片通过将数据拆分为更小的块(即分片),并将其存储在多个数据库服务器上来解决海量数据的存储,那么在 Redis 中的数据分片是通过 槽位机制 来实现的,集群将所有的数据划分为 16384 个槽位,每个槽位就是一个数据分片,每个节点负责其中一部分,那么在集群扩容或缩容时,通过给新节点分配槽位来实现数据迁移

Redis 集群 slots 分配与内核数据结构

那么已经知道了 Redis 集群中通过 slots 来实现数据分片,那么集群中的每个节点不仅存储了自己拥有的槽位,还存储了整个集群槽位以及哪个槽位属于哪个节点

每个节点分配好了自己的槽位之后,会把自己的槽位信息同步给集群中的其他的所有节点

在集群中的每个节点中,以下边的数据结构来存储集群的槽位信息以及自己所拥有的槽位信息

在这里插入图片描述

基于 slots 槽位的命令执行流程分析

比如客户端需要插入一个 key-value,那么该键值对肯定属于一个 slot,slot 一定属于一个节点,那么我们通过客户端去插入这个键值对时,客户端会先随机找一个节点发送命令过去,节点内部会计算这个 slot 属于哪个节点

通过 CRC16 算法对 key 值进行哈希,并且对 16384 取模来获取具体的槽位,再随便找一个节点查看集群槽位分配情况,如果该节点需要存放的槽位属于当前节点,直接执行命令就可以;如果不是自己的节点,那么该节点会返回给客户端一个 MOVED(slot + 目标地址),再将请求进行重定向

基于跳跃表的 slots 和 key 关联关系

在集群模式中,所有的数据被划分到 16384 个槽位中,每一个槽位都有一部分的数据,客户端在发送命令的时候,在 server 端也会计算 key 所属的槽位,就可以把数据放在槽位里

每次操作完 key-value 数据之后,对于这个 key,会使用专门的 skipList 跳跃表数据结构,来跟 slot 做一个关联

那么 slot 和 key 之间的关联关系是通过 skipList 来实现的

skipList 的结构如下,包括 4 部分:header(头结点)、tail(尾结点)、level(跳表层级)、length(跳表长度)

在这里插入图片描述

那么跳表中每个节点包含了:对象、score、BW、L1、L2…L32指针,那么在存储 key 与 slot 的对应关系时,对象字段存储的就是 key 的值,score字段存储的就是槽位的值,表示该 key 属于哪个 slot 槽位

集群扩容时的slots转移过程与ASK分析

如果在集群中加入新的节点,可以通过命令把某个节点上的一部分槽位转移到新的节点中去

那么 slots 的转移过程依赖于 clusterState 中的两个数据结构:clusterNode *migration_slots_to[16384]clusterNode* importing_slots_from[16384]

这两个数据结构都是指向了一个 clusterNode 数组

importing_slots_from[] 记录了槽位从哪些节点中转移过来,如果 importing_slots_from[i] 不是 null,而是指向了一个 clusterNode,那么表示正在从这个 clusterNode 中导入槽位 i

migration_slots_to[] 记录了槽位转移到哪些节点中去,如果 migration_slots_to[i] 不是 null,而是指向了一个 clusterNode,表示正在向这个 cluster 转移该槽位

那么在槽位的迁移过程中,会出现 ASK 错误:

即如果在转移的过程中,对一个节点中进行 key-value 操作,计算槽位之后,发现槽位并不在当前节点(已经被迁移走了),那么就返回客户端 ASK 错误,引导客户端去操作该槽位转移到的节点,那么客户端接收到 ASK 错误后,根据错误提供的 IP 地址和端口号,再去操作目标节点,在操作目标节点之前,会先发送 ASKING 命令,因为此时正在迁移过程中,槽位还在新节点的 importing_slots_from 中,如果不发送 ASKING 命令,目标节点此时还没有完成槽位迁移,会以为槽位还不在自己这里,就返回给客户端 MOVED 命令,让客户端又去找原来的节点了,完整流程如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/223217.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手摸手Element-ui路由VueRoute

后端WebAPI准备 https://router.vuejs.org/zh/guide/ https://v3.router.vuejs.org/zh/installation.html <template><el-table:data"tableData"style"width: 100%":row-class-name"tableRowClassName"><!-- <el-table-colum…

go atexit源码分析

文章目录 atexit源码解析UML类图样例一: 程序退出之前执行注册函数1.1 流程图1.2 代码分析 样例二&#xff1a;使用cancel取消注册函数2.1 cancel流程图2.2 代码分析 样例三&#xff1a;使用Fatal/Fatalln/Fatal执行注册函数3.1 Fatal/Fatalln/Fatal流程图3.2 代码分析 atexit源…

【shell】正则表达式和文本三剑客之grep和awk

目录 一、正则表达式 1.1用法 1.2表示字符匹配 1.3表示次数 1.4表示位置锚定 1.5表示分组或其他 1.6扩展正则表达式 二、grep命令 三、awk命令 3.1awk与vim的区别 3.2awk的语法 3.3基础用法 test1.提取磁盘的分区利用率 test2.提取用户名和uid号 test3.提取ip地址…

【uniapp】微信运行报错TypeError_ Cannot read property ‘FormData‘ of undefined

文章目录 一、报错详情&#xff1a;二、解决&#xff1a; 一、报错详情&#xff1a; 二、解决&#xff1a; npm install axios0.27.2 #或者 npm install axios1.3.4

Go 数字类型

一、数字类型 1、Golang 数据类型介绍 Go 语言中数据类型分为&#xff1a;基本数据类型和复合数据类型基本数据类型有&#xff1a; 整型、浮点型、布尔型、字符串复合数据类型有&#xff1a; 数组、切片、结构体、函数、map、通道&#xff08;channel&#xff09;、接口 2、…

livox 半固体激光雷达 gazebo 仿真 | 安装与验证

livox 半固体激光雷达 gazebo 仿真 | 安装与验证 livox 半固体激光雷达 gazebo 仿真 | 安装与验证livox 介绍安装验证 livox 半固体激光雷达 gazebo 仿真 | 安装与验证 livox 介绍 览沃科技有限公司&#xff08;Livox&#xff09;成立于2016年。为了革新激光雷达行业&#xf…

2019年8月21日 Go生态洞察:迁移到Go模块

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

数据结构和算法-树和二叉树的定义和基本术语和性质

文章目录 树的基本概念和相关术语相关的应用节点间的关系描述节点&#xff0c;树的属性描述有序树vs无序树树vs森林小结 树的相关性质考点1考点2考点3考点4考点5考点6小结 二叉树的相关概念和基本术语重要 &#xff08;五种状态&#xff09;特殊二叉树小结 二叉树的相关性质二叉…

AIGC文生图及工具产品简介

AIGC&#xff0c;全称是人工智能生成内容&#xff08;Artificial Intelligence Generated Content&#xff09;是继UGC&#xff08;用户生成内容&#xff09;&#xff0c;PGC&#xff08;平台生成内容&#xff09;后&#xff0c;利用人工智能技术&#xff0c;自动生成内容的生产…

人工智能入门教学——AI代理(AI Agent)

目录 一、简介 二、特征 三、结构 四、工作流程 五、类型 六、应用 一、简介 AI代理 (Artificial Intelligence Agent)是指使用人工智能技术和算法来执行特定任务、解决问题或实现目标的程序或系统。这些代理可以是简单的程序&#xff0c;也可以是复杂的系统&#xff0c…

排序篇(六)----排序小结(不用三连,混流量券)

排序篇(六)----排序小结 排序算法复杂度及稳定性分析 直接插入排序的算法复杂度&#xff1a; 最好情况下&#xff0c;当数组已经有序时&#xff0c;直接插入排序的时间复杂度为O(n)&#xff0c;其中n是数组的大小。最坏情况下&#xff0c;当数组逆序排列时&#xff0c;直接插…

【无头双向链表和链表练习题2】

文章目录 以给定值x为基准将链表分割成两部分&#xff0c;所有小于x的结点排在大于或等于x的结点之前输入两个链表&#xff0c;找出它们的第一个公共结点。给定一个链表&#xff0c;判断链表中是否有环无头双向链表的模拟实现ArrayList&#xff08;顺序表&#xff09;和LinkedL…