关于 Redis 中集群

哨兵机制中总结到,它并不能解决存储容量不够的问题,但是集群能。

  • 广义的集群:只要有多个机器,构成了分布式系统,都可以称之为一个“集群”,例如主从结构中的哨兵模式。

  • 狭义的集群:redis 提供的集群模式,该模式主要是解决存储空间不够的问题(拓展存储空间)

集群的基本原理

在哨兵模式中,本质上还是 redis 主从节点存储数据,就要求一个主节点/从节点,存储整个数据的“全集”,当数据量很大的时候就需要很大的内存,这时候把数据全保存在一台机器上就不太合适。

所以,就需要引入多台机器,每台机器存储一部分数据。

但是,并不是多引入机器就够了,每一台机器还要有对应的从节点,主要是为了在主节点挂了的情况下,进行数据备份。

怎么把数据分成多份(分片方法)

哈希求余

设有 N 个分片,使用[0, N - 1]这样的序号进行编号

针对某个给定的 key,先计算 hash 值,再把得到的结果 % N,得到的结果即为分片编号

但是,这样的方法在数据量持续增大,大到需要进一步增加机器的时候,或者缩容的时候,开销比较大。

因为机器的数量增多,就意味着 N 的大小变化了,求出的 hash 值也会变化,这时需要将原来的分片中的数据搬运到新的位置。

而且并不只是从一台数据搬运到另一台数据,还需要重新进行数据的备份。

所以,为了避免这么大的开销,往往不能直接在生产环境上操作,只能通过“替换”的方式实现;也就是不改变机器中存储的数据,而改变各台机器的主从关系。但这样的做法需要依赖更多的机器,成本更高,操作步骤复杂。

一致性哈希算法

为了降低上述的搬运开销,能够更高效扩容,业界提出来“一致性哈希算法”。

key 映射到分片序号的过程不再是简单求余,而是改为以下过程

  1. 把 0 - 2^32 - 1 这个数据空间,映射到一个圆环上,数据按照顺时针方向增长

     2. 假设当前存在三个分片,就把分片放到圆环的某个位置上

    3. 假定有一个 key,计算得到 hash 值 H,那么这个 key 就从 H 所在位置,顺时针往下找,找到的第一个分片即为该 key 所从属的分片

这就相当于,N 个分片的位置,把整个圆环分成了 N 个管辖区间,key 的 hash 值落在某个区间内,就归对应区间管理。

基于这种规则,连续的值不再是交替地出现在每一个分区中,而是连续的值处于一个分区,再增容或者缩容的时候,需要数据搬运的概率就大大降低了,需要搬运的数据也减少了。

但是,虽然搬运成本低了,但这几个分片上的数据量,可能会不再均匀(数据倾斜)。

哈希槽分区算法(Redis真正采用的方法)

为了解决上述问题(搬运成本高和数据分配不均匀),Redis cluster 引入了哈希槽(hash slots)算法。

hash_slot = clc16(key) % 16384

其中 clc16 也是一种 hash 算法,16384 是 16 * 1024,也就是 2^14。

相当于把整个哈希值,映射到 16384 个槽位上,也就是 [0, 16384]。

然后再把这些槽位比较均匀地分配给每个分片,每个分片的节点都需要记录自己持有哪些分片。

假设当前有三个分片,一种可能的分配方式:

  • 0 号分片:[0, 5461],共 5462 个槽位

  • 1 号分片:[5462, 10923],共 5462 个槽位

  • 2 号分片:[10924, 16383],共 5460 个槽位

这里的分片规则是很灵活的,每个分片持有的槽位也不一定连续。

每个分片的节点使用位图来表示自己持有哪些槽位,对于 16384 个槽位来说,需要 2048 个字节(2KB)大小的内存空间表示。

如果需要进行扩容,就可以针对原有的槽位进行重新分配。

一种可能的分配方式:

  • 0 号分片:[0, 4095],共 4096 个槽位

  • 1 号分片:[5462, 9557],共 4096 个槽位

  • 2 号分片:[10924, 15019],共 4096 个槽位

  • 3 号分片:[4096, 5461] + [9558, 10923] + [15020, 16383],共 4096个槽位

在实际使用 Redis 集群分片的时候,不需要手动指定哪些槽位分配给某个分片,只需要告诉某个分片应该持有多少个槽位即可,Redis 会自动完成后续的槽位分配,以及对应的 key 搬运的工作。

Redis 集群最多有 16384 个分片吗?

不是的,如果集群有 16384 个分片,就意味着每个分片上只有一个槽位。key 值需要先映射到槽位,再映射到分片。如果每个分片包含的槽位比较多,并且槽位个数相当,就可以认为包含的 key 的数量相当;但如果每个分片的槽位很少,就不能直观地反应出 key 的数量,因为经过 hash 映射后具体到哪个分片的随机性比较大。

而且,如果分片个数达到 1.6w 这么大,所需要的主机数可能会达到 4w 以上,集群规模太大,可用性就会很难保证,出故障的概率会变大。

实际上,Redis 的作者建议集群分片数不应该超过 1000.

为什么是 16384 个槽位?

  • 节点之间通过心跳包通信,心跳包中包含了该节点持有哪些 slots。这个是使用位图的结构表示的,表示 16384(16k)个 slots,需要的位图大小是 2KB。如果给定的 slots 数更多了,则需要消耗更多的空间,8KB来表示。这样的空间虽然对于内存来说不算什么,但是在频繁的网络心跳包中,是一个不小的开销。

  • 另一方面,Redis 集群一般不建议超过 1000 个分片。所以 16K 对于最大 1000 个分片来说是足够用的,同时也会使对应的槽位配置位图体积不至于很大。

故障处理

故障判定

集群中的所有节点,都会周期性的使用心跳包进行通信。

  1. 节点 A 给节点 B 发送 ping 包,B 就会给 A 返回一个 pong 包。ping 和 pong 处理 message type 属性之外,其他部分都是一样的。这里包含了集群的配置信息(该节点的 id,该节点从属于哪个分片,是主节点还是从节点,从属于谁,持有哪些 slots 的位图...)。

  2. 每个节点每秒钟都会给一些随机的节点发起 ping 包,而不是全发一遍。这样设定是为了避免在节点很多的时候,心跳包也非常多(比如有 9 个节点,如果全发,就是 9 * 8 有 72 组心跳了,而且这是按照 N^2 这样的级别增长的)。

  3. 当节点 A 给节点 B 发起 ping 包,B 不能如期回应的时候,此时 A 就会尝试重置和 B 的 TCP 连接,看能否连接成功。如果仍然连接失败,A 就会把 B 设为 PFAIL 状态(相当于主观下线)。

  4. A 判定 B 为 FAIL 之后,会通过 redis 内置的 Gossip 协议,和其他节点进行沟通,向其他节点确认 B 的状态(每个节点都会维护一个自己的“下线列表”,由于视角不同,每个节点的下线列表也不一定相同)。

  5. 此时 A 发现其他很多节点,也认为 B 为 FAIL,并且数目超过总集群个数的一半,那么 A 就会把 B 标记成 FAIL(相当于客观下线),并把这个消息同步给其他节点(其他节点收到之后,也会把 B 标记成 FAIL)。

至此,B 就彻底被判定为故障节点了。

某个或某些节点宕机,有时候会引起整个集群都宕机(成为 FAIL 状态)。

以下三种情况会出现集群宕机:

  • 某个分片,所有的主节点和从节点都挂了。

  • 某个分片,主节点挂了,但没有从节点。

  • 超过一半的 master 节点挂了。

核心原则是保证每个 slots 都能正常工作(存取数据)

故障迁移

上述例子中,B 故障,并且 A 把 B FAIL 的消息告知集群中的其他节点。

  • 如果 B 是从节点,则不需要进行故障迁移。

  • 如果 B 是主节点,则会由 B 的从节点(例如 C 和 D)触发故障迁移。

所谓的故障迁移,就是把从节点提拔成主节点,继续给整个 redis 集群提供支持。

具体流程如下:

  1. 从节点判定自己是否具有参选资格。如果从节点和主节点已经太久没有通信(此时认为从节点中的数据和主节点相差太大了),时间超过阈值,就失去竞选资格。

  2. 具有资格的结点,例如 C 和 D,就会先休眠一段时间。休眠时间 = 500ms 基础时间 + [0, 500ms] 随机时间 + 排名 * 1000ms。offset 的值越大,则排名越靠前。

  3. 例如 C 的休眠时间到了,C 就会给其他所有集群中的节点,进行拉票操作。但只有主节点才有投票资格。

  4. 主节点就会把自己的票投给 C(每个主节点只有 1 票)。当 C 收到的票数超过主节点数目的一半,C 就会晋升成主节点(C 自己负责执行 slaveof no one,并让 D 执行 slaveof C)。

  5. 同时,C 还会把自己成为主节点的消息,同步给其他集群的节点,大家也都会更新自己保存的集群结构信息。

上述选举的过程,称为 Raft 算法,是一种在分布式系统中广泛使用的算法。

在随机休眠时间的加持下,基本上就是谁先唤醒,谁就能竞选成功。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQLWorkbench导出sql文件

MySQLWorkbench导出sql文件 前言效果图导出操作选择要导出的数据库遇到的问题解决问题查看mysql路径前言 在完成数据库搭建之后,需要为上线做准备,那么就需要导出数据库的建库sql了 本篇文章讲解的是mysql Workbench 导出数据建库脚本 效果图 导出操作 选择要导出的数据库…

java 深拷贝和浅拷贝

深拷贝和浅拷贝的概念 浅拷贝:只对基本数据类型进行拷贝,针对于引用数据类型,只是拷贝了对象的引用,没有真实的创建一个新的对象就是浅拷贝 深拷贝:在对引用数据类型拷贝过程中,创建了一个新的对象&#xf…

Dell服务器根据GPU温度调整风扇转速

前言 dell服务器自动风扇是根据CPU温度来调速的,我跑AI的时候cpu温度不高但是GPU温度很高导致显卡卡死PVE虚拟机直接挂起无法运行,我看了下也没有基于显卡温度调速的脚本,于是我就自己写了一个 基于ipmi工具 乌班图等linux先安装ipmi apt …

算法金 | A - Z,115 个数据科学 机器学习 江湖黑话(全面)

大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 机器学习本质上和数据科学一样都是依赖概率统计,今天整整那些听起来让人头大的机器学习江湖黑话 A - C A/B Testing (A/B …

电子电器架构——智能座舱设备终端

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

电路笔记 : 嘉立创EDA 导入、查找、设计管理器(快速寻找网络标签)功能+DRC错误检查和处理

导入功能 查找功能 可查找多种类型,如原件名称、网络标签等 设计管理器 图层查看 DRC错误 规则设置 线距问题 大多数PCB制造商能够可靠地生产5 mil间距的走线和间隙。这是一个常见的标准,适合大多数消费级和工业级电子产品。在5 mil以上的间距&#xff…

设计软件有哪些?照明工具篇,渲染100邀请码1a12

阴影和照明涉及到图片的真实感和氛围,所以熟练使用照明工具是设计师的必备能力,这次我们介绍一些照明工具。 1、VRaySun VRaySun是VRay渲染器中的一个功能,用于模拟太阳光源。它是一种方便易用的光源类型,能够产生逼真的日光效果…

MySQL与PostgreSQL关键对比三(索引类型)

目录 索引类型 B-tree 索引 Hash 索引 Full-text 索引 GiST 索引 GIN 索引 BRIN 索引 索引创建示例 MySQL PostgreSQL 结论 以下SQL语句的执行如果需要开发工具支持,可以尝试使用SQLynx或Navicat来执行。 MySQL和PostgreSQL在索引方面有许多相似之处&am…

Puppeteer实战案例:自动化抓取社交媒体上的媒体资源

在当今数字化时代,社交媒体已成为人们获取信息、分享生活和进行商业推广的重要平台。随着社交媒体内容的爆炸性增长,自动化抓取社交媒体上的媒体资源变得尤为重要。本文将介绍如何使用Puppeteer这一强大的自动化工具来实现这一目标。 1. Puppeteer简介 …

从零开始理解AdaBoost算法:设计思路与算法流程(二)【权值更新与加权表决、数学公式】

设计思路 AdaBoost算法属于Boosting算法家族中的一种,其基本思路是将多个弱分类器组合成一个强分类器。 “强分类器”是指一个分类准确率较高的模型“弱分类器”则是指分类准确率略高于随机猜测的简单模型。 AdaBoost的核心思想是通过 加权 的方式逐步提高分类器…

在Modelarts上微调量化Llama3,并用docker部署

本文概述 本文先使用llama-factory去微调llama3大模型,然后使用llama.cpp去量化模型并打包为docker部署到服务器上让qq机器人能够调用服务,实现qq群内问答。 效果展示 环境准备 本文使用华为云的Modelarts的notebook去进行的模型微调 ubuntu20.04&#x…

黑马es学习

es 0. 基础概念0.1 倒排索引0.2 文档、索引0.3 与mysql对比 1 基本操作1.1 mapping 索引库操作1.2 单个文档CRUD 3. DSL查询3.1 查询所有3.2 全文检索3.3 精确查询3.4 复合查询-相关性得分3.5 分页3.6 高亮3.7 总结 2. RestClientmysql与es数据同步es集群去重 黑马视频 官方使…

【李宏毅-生成式 AI】Spring 2024, HW5:LLM Fine-tuning 实验记录

文章目录 1. Task Overview2. Overall Workflow3. Dataset 介绍4. 代码介绍4.1 环境介绍4.2 下载 dataset4.3 下载并加载模型4.2 Notebook 代码1)import 部分2)固定 seed3)加载 LLM4)加载 tokenizer5)设置解码参数6&am…

【Linux系统化学习】传输层——TCP协议

目录 预备知识 全双工协议 协议缓冲区 TCP协议 TCP协议格式 六个标志位 两个问题 确认应答机制 流量控制 超时重传机制 连接管理机制 CLOSE_WAIT状态 TIME_WAIT状态 滑动窗口 拥塞控制 延迟应答 捎带应答 粘包问题 TCP的异常情况 TCP小结 TCP/UDP协议对比…

数据结构:插入排序和希尔排序

插入排序 逆序的情况下: 时间复杂度:O(N^2) 空间复杂度:O(1) 顺序的情况下: 时间复杂度:O(N) 空间复杂度…

【教程】怎么获取IPV6,我教你

1.png 所以IPV6诞生了 IPV6拥有超大的地址空间 IPv4 采用 32 位地址长度,可以为我们提供 2^32 大约 43 亿个地址,而 IPv6 采用 128 位地址长度,为我们提供了 2^128 个地址 博主的家里用的宽带是移动宽带,众所周知,…

【qt】绘图

绘图 一.画家二.绘图事件三.坐标体系四.画笔1.setColor2.setWidth3.setStyle4.setCapStyle5.setJoinStyle6.给画家配置笔 五.画刷1.setColor2.setStyle3.给画家设置刷子 六.用到的类汇总1.QRect 矩形2.QPoint 点3.QImage 图片4.QPixmap 图片5.QLine 线6.QPainterPath 路径 七.开…

关于用宽带(拨号)连接VPN无法上网,但是wifi或者热点就可以的问题

参考链接:https://zhuanlan.zhihu.com/p/580929250https://zhuanlan.zhihu.com/p/580929250 https://blog.csdn.net/Yaoyao2024/article/details/132245249文章浏览阅读10w次,点赞161次,收藏515次。很多同学在学习访问学校提供的资源时或者一…

selenium自动化测试入门 —— 上传文件

selenium无法识别非web的控件,上传文件窗口为系统自带,无法识别窗口元素。 上传文件有两种场景:input控制上传和非input控件上传。 大多数情况都是input控件上传文件,只有非常少数的使用自定义的非input上传文件。 一、input控…

python实践笔记(一): 模块和包

1. 写在前面 最近在重构之前的后端代码,借着这个机会又重新补充了关于python的一些知识, 学习到了一些高效编写代码的方法和心得,比如构建大项目来讲,要明确捕捉异常机制的重要性, 学会使用try...except..finally&…