当前位置: 首页 > news >正文

【Redis】--集群

文章目录

  • 1. Redis集群
    • 1.1 基本概念
    • 1.2 数据分片算法
      • 1.2.1 哈希求余
      • 1.2.2 一致性哈希算法
      • 1.2.3 哈希槽分区算法(Redis使用的分片算法)
    • 1.3 主节点宕机处理流程
      • 1.3.1 故障判定(识别出某个主节点是否是挂了)
      • 1.3.2 故障迁移

1. Redis集群

1.1 基本概念

广义上的集群:只要是多个机器,构成了分布式系统,都可以被称为一个集群。

狭义上的集群:主要是解决存储空间不足的问题。

采用Redis集群的方式就是引入多台机器,每台机器存储一部分数据。

在这里插入图片描述

1.2 数据分片算法

1.2.1 哈希求余

借助哈希函数,吧一个key映射到整数,再针对数组的长度求余,就可以得到一个数据下标。

设有 N 个分片, 使⽤ [0, N-1] 这样序号进行编号.
针对某个给定的 key, 先计算 hash 值, 再把得到的结果 % N, 得到的结果即为分片编号.
在这里插入图片描述
后续如果要取某个 key 的记录, 也是针对 key 计算 hash , 再对 N 求余, 就可以找到对应的分片编号了.

优点: 简单高效,数据分布均匀。

缺点: 一旦需要进行扩容,原有的映射规则就被破坏了,需要搬运大量的数据,开销极大。

在这里插入图片描述
这种方式往往是不能直接在生产环境上操作的,只能通过替换的方式来实现扩容。

1.2.2 一致性哈希算法

上面的哈希求余的方法判断key是属于哪个分片的,是交替出现的,导致搬运成本大。在一致性哈希中把交替出现改成了连续出现。

  1. 把 0 -> 2^32-1 这个数据空间, 映射到⼀个圆环上. 数据按照顺时针⽅向增长.
    在这里插入图片描述
  2. 假设当前存在三个分⽚, 就把分⽚放到圆环的某个位置上.
    在这里插入图片描述
  3. 假定有⼀个 key, 计算得到 hash 值 H, 那么这个 key 映射到哪个分片呢? 规则很简单, 就是从 H 所在位置, 顺时针往下找, 找到的第⼀个分片, 即为该 key 所从属的分片.
    在这里插入图片描述
    扩容:
    原有分片在环上的位置不动,在环上新安排一个分片位置即可。
    在这里插入图片描述
    上面新添加了一个3号分片,只需要把0号分片上的部分数据搬运给3号分片即可。

缺点: 几个分片上的数据不均匀了。

1.2.3 哈希槽分区算法(Redis使用的分片算法)

哈希槽分区算法本质上就是把一致性哈希和哈希求余结合一下。

hash_slot = crc16(key) % 16384

16384 = 214
crc16是一种hash算法
hash_slot:哈希槽

相当于是把整个哈希值映射到16384个槽位上,然后再把这些槽位比较均匀的分配给每个分片。每个分片都记录着自己持有哪些分片。

假设当前有三个分⽚, ⼀种可能的分配⽅式:
> 0 号分⽚: [0, 5461], 共 5462 个槽位
> 1 号分⽚: [5462, 10923], 共 5462 个槽位
> 2 号分⽚: [10924, 16383], 共 5460 个槽位

虽然不是严格意义上的均匀,但是差异非常小。这里只是一种可能的分片方式,实际的分片是非常灵活的,每个分片持有的槽位号,可能是连续的,也 可能真连续的。

每个分片都会使用位图这样的数据结构表示当前有多少个槽位。
16384个bit位,每一个bit位用0/1来区分自己整个分片当前是否持有 该槽位。
16384个bit位 = 2048个字节 = 大约2KB。

扩容
如果需要进行扩容, 比如新增⼀个 3 号分片, 就可以针对原有的槽位进行重新分配.
比如可以把之前每个分片持有的槽位, 各拿出⼀点, 分给新分片.
⼀种可能的分配方式:
• 0 号分片: [0, 4095], 共 4096 个槽位
• 1 号分片: [5462, 9557], 共 4096 个槽位
• 2 号分片: [10924, 15019], 共 4096 个槽位
• 3 号分片: [4096, 5461] + [9558, 10923] + [15019, 16383], 共 4096 个槽位

Reds中,当前某个分片包含哪些槽位都是可以手动配置的。

问题1:Redis集群是最多有16384个分片吗?

key是先映射到槽位上,再映射到分片上的。这样的话每个分片上只有一个槽位,那么就很难保证数据再各个分片上的均衡性。
如果每个分片包含的槽位比较多,如果槽位个数相当,就可以认为包含的key数量相当。
如果每个分片包含的槽位非常少,槽位个数不一定能直观的反应到key的数目。

问题2:为什么是16384个槽位
节点之间通过心跳包通信,心跳包中包含了该节点持有哪些slots.这个是使⽤位图这样的数据结构表示的. 表示 16384 (16k) 个 slots, 需要的位图大小是 2KB. 如果给定的 slots 数更多了, 比如 65536 个了, 此时就需要消耗更多的空间, 8 KB 位图表示了. 8 KB, 对于内存来说不算什么, 但是在频繁的网络心跳包中, 还是⼀个不小的开销的.

另⼀⽅⾯, Redis 集群⼀般不建议超过 1000 个分⽚. 所以 16k 对于最⼤ 1000 个分⽚来说是⾜够⽤的, 同时也会使对应的槽位配置位图体积不⾄于很⼤.

1.3 主节点宕机处理流程

1.3.1 故障判定(识别出某个主节点是否是挂了)

集群中所以接待你都会周期性的使用心跳包进行通信。

  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 为 PFAIL 之后, 会通过 redis 内置的 Gossip 协议, 和其他节点进⾏沟通, 向其他节点确认 B 的状态. (每个节点都会维护⼀个⾃⼰的 “下线列表”, 由于视⻆不同, 每个节点的下线列表也不⼀定相同).
  5. 此时 A 发现其他很多节点, 也认为 B 为 PFAIL, 并且数⽬超过总集群个数的⼀半, 那么 A 就会把 B 标记成 FAIL (相当于客观下线), 并且把这个消息同步给其他节点(其他节点收到之后, 也会把 B 标记成 FAIL).

⾄此, B 就彻底被判定为故障节点了.

1.3.2 故障迁移

上后面的B如果是从节点,那么就不需要进行故障迁移了。
如果是主节点,那么就需要进行故障迁移了。

故障迁移就是把从节点提拔成主节点(Raft算法),继续给整个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 还会把⾃⼰成为主节点的消息, 同步给其他集群的节点. ⼤家也都会更新⾃⼰保存的集群结构
    信息.

注意这里和哨兵是不一样的。哨兵是先选出一个leader,,leader负责找出一个从节点升级成主节点;而集群是直接投票选出一个新的主节点。


文章转载自:

http://3P8rqqO4.fgLyb.cn
http://EzSbh6Pm.fgLyb.cn
http://S1VEo22a.fgLyb.cn
http://4YoGTuz7.fgLyb.cn
http://mDNkK12M.fgLyb.cn
http://PzncuFui.fgLyb.cn
http://44tuebVD.fgLyb.cn
http://ivJfCkph.fgLyb.cn
http://vDorJDIx.fgLyb.cn
http://C7tuTjyT.fgLyb.cn
http://vnqwln7e.fgLyb.cn
http://5utz06LM.fgLyb.cn
http://U9gSl6LZ.fgLyb.cn
http://ka4IzaFz.fgLyb.cn
http://bHIo1SZ8.fgLyb.cn
http://qmYLYvF3.fgLyb.cn
http://XxeZNA9R.fgLyb.cn
http://znjhkq5q.fgLyb.cn
http://EzNBtOpp.fgLyb.cn
http://rmRvVsZq.fgLyb.cn
http://X5avQ9dl.fgLyb.cn
http://5Uc0AxRW.fgLyb.cn
http://SbEQJhJs.fgLyb.cn
http://U5D5W8sk.fgLyb.cn
http://eEKEYNTY.fgLyb.cn
http://Xuk6mecU.fgLyb.cn
http://6f7uvF9H.fgLyb.cn
http://h2VF7yp9.fgLyb.cn
http://2FXe3xrR.fgLyb.cn
http://4zhTExnI.fgLyb.cn
http://www.dtcms.com/a/386992.html

相关文章:

  • TRUNCATE还是DELETE?MySQL高效清空表的选择策略与实战指南
  • 【AI】AI评测入门(四):Evaluator Prompt拆解
  • Redis以`后台`方式启动方法
  • 【每日算法】找出字符串中第一个匹配项的下标 LeetCode
  • 【12】新国都 ——新国都 嵌入式 第一轮一面,技术面,校招,面试问答记录
  • 线程池-面试
  • 设计模式学习笔记(一)
  • 贪心算法应用:旅行商问题最近邻算法(TSP Nearest Neighbor)
  • 高系分七:软件工程
  • spark hive presto doris 对substr函数的差异
  • webpack5
  • M:Dijkstra算法求最短路径
  • C++11 atomic
  • 工作中真正常用的 git 操作
  • 【Java】P5 Java流程控制——分支结构详解
  • 下载 | Win10 2021官方精简版,预装应用极少!(9月更新、Win 10 IoT LTSC 2021版、适合老电脑安装)
  • 【面试场景题】交易流水表高qps写入会有锁等待或死锁问题吗
  • 嵌入式系统arm高级系统调试技能-24./proc/slabinfo 文件解读与内存异常分析
  • 关于单片机编程的循环以及全局变量应用的思考
  • C++string类详解
  • 卷积神经网络搭建实战(一)-----torch库中的MNIST手写数字数据集(简明版)
  • 2025 Android 知识体系总结(含面试要点,持续补充,更新中...)
  • elementui中表单先上传但不请求接口,点击按钮后在请求接口的方式上传文件,及校验
  • el-input自动填充与设置input背景色无效
  • java设计模式-工厂模式(文件上传)
  • Keras+Flask手写数字识别Web应用
  • PPTist+cpolar:开源演示文稿的远程创作方案
  • Chapter8—组合模式
  • vmware的ub系统长时间不动会黑屏
  • 从0到1打造一个能上传任意GeoJSON的交互式Web地图