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

Redis06 - Redis集群为什么是Hash槽而不是一致性哈希

Redis集群为什么是Hash槽而不是一致性哈希

文章目录

  • Redis集群为什么是Hash槽而不是一致性哈希
    • 一:一致性哈希回顾
    • 二:不同的计算方式
    • 三:再谈Redis Cluster集群
      • 1:哈希槽
      • 2:增加节点
      • 3:减少节点
      • 4:客户端访问节点数据
      • 5:smart客户端
    • 四:所以为什么
    • 五:扩展
      • 1:为什么哈希槽数量是16384

一:一致性哈希回顾

详情见“架构 -> 分布式与微服务 -> 分布式理论”

一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时,发生过多的数据迁移的问题。

算法是对 2^32进行取模运算的结果值虚拟成一个圆环,环上的刻度对应一个 0~2^32 - 1 之间的数值。

通过虚拟节点的方式很好的处理了数据不平衡问题。

在这里插入图片描述

二:不同的计算方式

Redis Cluster的实现,也是用了Hash的方式将键值按照一定算法分配到各个节点的,但是却没有使用一致性哈希算法,而是引入了哈希槽的概念

先看下一致性哈希和哈希槽在计算上的区别:

在这里插入图片描述
图中A、B、C表示的是三个节点,k1和k2表示的是key:

一致性哈希是经过 hash() 函数计算后对 2^32 取模的值虚拟成一个圆环

哈希槽是将每个key通过CRC16计算得到一个16bit的值,然后16bit值再对16384取模来决定放置哪个槽

虽说在计算方式上有区别,好像都解决了数据均衡的问题,应该都是不错的选择。

三:再谈Redis Cluster集群

1:哈希槽

集群将数据划分为 16384 (2^14)个槽位(哈希槽),每个Redis服务节点分配了一部分槽位

因为槽位的信息存储于每个节点中,客户端请求的key通过CRC16校验后对16384取模来决定放置哪个槽,这样也就定位到指定的节点中。

在这里插入图片描述
上图中 key 【小许】和【code】经过 CRC16 计算后再对哈希槽总个数 16384 取模

得到哈希槽位置分别是在888的节点A上和10924的节点C上面。

2:增加节点

新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot(槽)到D上,会变成这样:

在这里插入图片描述
此时服务A、B、C、D通过分配各自有了对应的哈希槽

新增节点后集群会自动进行哈希槽的重新平均分配,比如上图中四个节点中每个节点的槽位数是:18384 / 4 = 4096。

当然这个你使用命令 【cluster addslots】为每个节点自定义分配槽的数量

这里有个特点,如果我们节点的机器性能有差异,那就可以为性能好的,配置更多槽位,更好的利用机器性能。

3:减少节点

如果减少一个节点C,redis cluster同样会自动进行槽数量的重新计算分配,然后后变成下面样子:

在这里插入图片描述
删除节点C之后,此时服务A、B节点中每个节点的槽位数是:18384 / 2 = 8192

4:客户端访问节点数据

Redis cluster的主节点各自负责一部分槽,我们来看下来自客户端的请求的key是如何定位到具体的节点,然后返回对应的数据的。

在这里插入图片描述
来自Redis-Cli客户端的请求连接到的是集群中的任何一个节点

首先检查当前key是否存在集群中的节点

  • 通过CRC16(key)/ 16384计算出slot

  • 查询负责该slot负责的节点是否存在

在该节点的话就直接就直接返回key对应的结果

不在该节点的话,那么会 MOVED重定向(包含槽位和目标地址)指引客户端转向至正确的节点,并再次发送之前执行的命令

这种方式弊端很明显,每次执行命令前都可能现在Redis节点上进行MOVED重定向才能找到要执行命令的节点,额外增加了IO开销。

大多数开发语言的Redis客户端都采用 Smart客户端 支持集群协议,让整个访问就更高效。

5:smart客户端

开发语言写的Redis客户端都会采用Smart客户端来支持访问集群。

主要是在内部维护哈希槽–节点的映射关系,这样就可以在Smart客户端实现键到节点的查找,避免了再进行MOVED重定向。

不过第一步还是初始化时会选择一个运行节点,初始化槽和节点映射关系。

在这里插入图片描述

四:所以为什么

有的回答是“当节点太少时,一致性哈希容易数据分布不均匀更容易导致雪崩”,但是一致性哈希早就有虚拟节点解决这个问题

如果非要说极限情况,那么Redis哈希槽,也有可能某些hash 区间的值特别多,然后导致该节点导访问过于集中的问题

下面的是更加令人信服的答案:

  • 当发生扩容时候,Redis可配置映射表的方式让哈希槽更灵活,可更方便组织映射到新增server上面的slot数,比一致性hash的算法更灵活方便
  • 在数据迁移时,哈希槽直接将一个slot对应的数据全部迁移,实现更简单
  • 可以灵活的分配槽位,比如性能更好的节点分配更多槽位,性能相对较差的节点可以分配较少的槽位

五:扩展

1:为什么哈希槽数量是16384

我们知道一致性哈希算法是对2的32次方取模,而哈希槽是对2的14次方取模

因为Redis作者认为这样做不太值得;并且一般情况下一个redis集群不会有超过1000个master节点,所以16k的槽位是个比较合适的选择。

在这里插入图片描述
所以总结下来有如下的因素:

  • Redis节点间通信时,心跳包会携带节点的所有槽信息,它能以幂等方式来更新配置。
    • 如果采用 16384 个插槽,占空间 2KB (16384/8);
    • 如果采用 65536 个插槽,占空间 8KB (65536/8);
  • Redis Cluster 不太可能扩展到超过 1000 个主节点,太多可能导致网络拥堵。
  • 16384 个插槽范围比较合适,当集群扩展到1000个节点时,也能确保每个master节点有足够的插槽

http://www.kler.cn/a/538036.html

相关文章:

  • React受控组件的核心原理与实战精要
  • 音频进阶学习十一——离散傅里叶级数DFS
  • 计算机视觉的研究方向、发展历程、发展前景介绍
  • 在 Ubuntu 上安装 MySQL 的详细指南
  • IDEA中Resolving Maven dependencies卡着不动解决方案
  • 从 Facebook 到元宇宙:社交网络的技术进化与前景
  • ubuntu 本地部署deepseek r1 蒸馏模型
  • 用 Lambda 表达式处理 Java Stream 流操作
  • 装备库室管控系统|支持国产化、自主研发
  • 【医院运营统计专题】2.运营统计:医院管理的“智慧大脑”
  • 【Milvus】向量数据库pymilvus使用教程
  • 2022java面试总结,1000道(集合+JVM+并发编程+Spring+Mybatis)的Java高频面试题
  • Vue | 透传 Attributes(非 prop 的 attribute )
  • STM32 硬件I2C读写MPU6050
  • V8 GC垃圾回收
  • 一步一步生成音乐类小程序的详细指南,结合AI辅助开发的思路
  • android studio无痛入门
  • 西安科技创新领跑者:树莓集团以科技创新赋能产业生态圈
  • Milvus 存储设计揭秘:从数据写入到 Segment 管理的全链路解析
  • 深入浅出Log4j2:从入门到实战应用指南
  • C语言基础系列【6】流程控制
  • 快速建立私有化知识库(私有化训练DeepSeek,通过ollama方式)
  • python 使用OpenAI Whisper进行显卡推理语音翻译
  • 探秘树莓集团海南战略:文创领军者的市场破局之路
  • 【Go语言快速上手】第二部分:Go语言进阶
  • opencv打开摄像头出现读取帧错误问题