为什么Redis使用哈希槽而不是一致性哈希

今天我们聊个知识点为什么Redis使用哈希槽而不是一致性哈希。

往期回顾

之前小许用图文并茂的方式用一期内容让大家快速了解了一致性哈希算法,看过的朋友应该还有印象,没看过的朋友可以点击这里看一遍《精通分布式,不了解Hash一致性算法?》。

这里我们再简单回顾下:一致性哈希算法就很好地解决了分布式系统在扩容或者缩容时,发生过多的数据迁移的问题。算法是对 2^32 进行取模运算的结果值虚拟成一个圆环,环上的刻度对应一个 0~2^32 - 1 之间的数值。通过虚拟节点的方式很好的处理了数据不平衡问题。

图片

不同的计算方式

不知道朋友们记不记得Redis Cluster的实现,也是用了Hash的方式将键值按照一定算法分配到各个节点的,但是却没有使用一致性哈希算法,而是引入了哈希槽的概念!这是为什么呢?🤔🤔我们先看下一致性哈希和哈希槽在计算上的区别

图片

图中A、B、C表示的是三个节点,k1和k2表示的是key:

  • 一致性哈希是经过 hash() 函数计算后对 2^32 取模的值虚拟成一个圆环
  • 哈希槽是将每个key通过CRC16计算得到一个16bit的值,然后16bit值再对16384取模来决定放置哪个槽

虽说在计算方式上有区别,好像都解决了数据均衡的问题,应该都是不错的选择。OK,本文将先对Redis集群节点增减时如何进行哈希槽的分配进行分享,再回过头看为什么Redis 集群没有使用一致性hash,而是引入了哈希槽的概念的原因究竟是什么!

Redis Cluster集群

Redis集群是一种分布式数据库方案,通过服务器分片技术进行数据管理,我们来对它进行一个归纳总结。

哈希槽

集群将数据划分为 16384 (2^14)个槽位(哈希槽),每个Redis服务节点分配了一部分槽位,因为槽位的信息存储于每个节点中,客户端请求的key通过CRC16校验后对16384取模来决定放置哪个槽,这样也就定位到指定的节点中。

图片

​上图中 key 【小许】和【code】经过 CRC16 计算后再对哈希槽总个数 16384 取模,得到哈希槽位置分别是在888的节点A上和10924的节点C上面。重点:每个节点都会记录哪些槽分配给了自己,哪些槽被分配给了其他节点

增加节点

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

图片

​此时服务A、B、C、D通过分配各自有了对应的哈希槽,新增节点后集群会自动进行哈希槽的重新平均分配,比如上图中四个节点中每个节点的槽位数是:18384 / 4 = 4096。当然这个你使用命令 【cluster addslots】为每个节点自定义分配槽的数量,这里有个特点,如果我们节点的机器性能有差异,那就可以为性能好的,配置更多槽位,更好的利用机器性能。

减少节点

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

图片

删除节点C之后,此时服务A、B节点中每个节点的槽位数是:18384 / 2 = 8192

客户端访问节点数据

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

图片

来自Redis-Cli客户端的请求连接到的是集群中的任何一个节点

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

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

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

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

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

相信你也和小许一样觉得这种方式弊端很明显,每次执行命令前都可能现在Redis节点上进行MOVED重定向才能找到要执行命令的节点,额外增加了IO开销。不过大多数开发语言的Redis客户端都采用 Smart客户端 支持集群协议,让整个访问就更高效。我们来看下是如何实现的!

smart客户端

开发语言写的Redis客户端都会采用Smart客户端来支持访问集群。主要是在内部维护哈希槽--节点的映射关系,这样就可以在Smart客户端实现键到节点的查找,避免了再进行MOVED重定向。不过第一步还是初始化时会选择一个运行节点,初始化槽和节点映射关系。

我们看下图:

图片

​上面我们简单讲了下Redis-Cluster中哈希槽和增删节点槽位的转移分配,回归正题。

为什么Redis是使用哈希槽而不是一致性哈希呢?

有人可能会说是当节点太少时,一致性哈希容易数据分布不均匀更容易导致雪崩。但是看过我开头分享的一致性哈希文章,通过引入虚拟节点是基本可以避免这个问题的如果非要说极限情况,那么Redis哈希槽,也有可能某些hash 区间的值特别多,然后导致该节点导访问过于集中的问题。抛开这些极端情况,通过上面对哈希槽的总结,以下这些是更值得信服的回答:

  • 当发生扩容时候,Redis可配置映射表的方式让哈希槽更灵活,可更方便组织映射到新增server上面的slot数,比一致性hash的算法更灵活方便。

  • 在数据迁移时,一致性hash 需要重新计算key在新增节点的数据,然后迁移这部分数据,哈希槽则直接将一个slot对应的数据全部迁移,实现更简单

  • 可以灵活的分配槽位,比如性能更好的节点分配更多槽位,性能相对较差的节点可以分配较少的槽位

为什么Redis Cluster哈希槽数量是16384?

我们知道一致性哈希算法是对2的32次方取模,而哈希槽是对2的14次方取模。Redis作者认为这样做不太值得;并且一般情况下一个redis集群不会有超过1000个master节点,所以16k的槽位是个比较合适的选择。Redis作者的回答在这里:why redis-cluster use 16384 slots? · Issue #2576 · redis/redis

图片

​总结起来主要有以下因素

  •  Redis节点间通信时,心跳包会携带节点的所有槽信息,它能以幂等方式来更新配置。如果采用 16384 个插槽,占空间 2KB (16384/8);如果采用 65536 个插槽,占空间 8KB (65536/8)。

  •  Redis Cluster 不太可能扩展到超过 1000 个主节点,太多可能导致网络拥堵。

  •  16384 个插槽范围比较合适,当集群扩展到1000个节点时,也能确保每个master节点有足够的插槽

这也就是为什么哈希槽的数量是16384了!

【信号处理】VMD-fft-hht模板,直接导入自己数据就能处理(Matlab代码实现)内容概要:本文介绍了一个基于Matlab的信号处理模板工具包,重点实现了VMD(变分模态分解)、FFT(快速傅里叶变换)和HHT(希尔伯特-黄变换)三种信号处理方法的集成化流程。该模板支持用户直接导入自身采集的数据进行一键式处理,适用于非平稳、非线性信号的去噪、特征提取与频谱分析,广泛应用于机械故障诊断、生物医学信号处理和工程振动分析等领域。文档还列举了多个相关科研方向和技术服务内容,涵盖智能优化算法、机器学习、路径规划、电力系统仿真等多个领域,展示了其在科研仿真中的通用性和扩展性。; 适合人群:具备一定Matlab编程基础的研究生、科研人员及工程技术人员,尤其适合从事信号处理、故障诊断、数据分析等相关领域的研究人员;初学者可通过模板快速上手实践。; 使用场景及目标:①对复杂信号进行高效分解与特征提取;②实现从原始信号到频谱分析的全流程自动化处理;③作为科研项目或论文复现的基础工具,提升研究效率;④结合其他优化与机器学习算法开展综合性课题研究。; 阅读建议:建议使用者先熟悉VMD、FFT和HHT的基本原理,再结合实际数据运行模板代码,逐步调试参数以优化分解效果;同时可参考文中提供的其他资源链接,拓展至多学科交叉应用。
**Redis Cluster 并没有使用一致性哈希算法**,而是采用了 **虚拟hash slot)分区机制**。 ### Redis Cluster 的数据分片方式:哈希Hash Slot) - Redis Cluster 将整个键空间划分为 **16384 个哈希slots)**。 - 每个 key 通过以下公式映射到一个: ```bash slot = CRC16(key) % 16384 ``` - 所有都被分配给集群中的各个主节点(master nodes),每个主节点负责一部分。 - 当客户端请求某个 key 时,先计算它属于哪个,再路由到负责该的节点。 例如: ```bash SET mykey "hello" # 计算 CRC16("mykey") % 16384 → 假设结果是 5000 # 那么这个 key 就由负责 slot 5000 的节点处理 ``` ### 与一致性哈希的区别: | 特性 | Redis Cluster(哈希) | 一致性哈希 | |------|--------------------------|------------| | 分片单位 | 16384 个哈希 | 哈希环上的点 | | 节点增减影响 | 只需迁移部分的数据 | 影响邻近区域数据 | | 负载均衡控制 | 精确控制每个节点的范围 | 依赖虚拟节点实现均衡 | | 实现复杂度 | 中等,集中管理分配 | 较高,需维护环结构 | | 扩展性 | 高,支持动态重新分片 | 高,但可能不均匀 | ### 为什么 Redis 选择哈希不是一致性哈希? 1. **更精确的负载均衡**:可以手动或自动将 16384 个均匀分配给各节点。 2. **便于管理和迁移**:扩容或缩容时,只需将一些从旧节点迁移到新节点,过程可控。 3. **支持多节点同时服务**:每个可明确归属某主节点,并有对应的从节点复制。 4. **避免数据倾斜**:一致性哈希在节点少时容易分布不均,而哈希可通过配置优化。 ### 示例:默认情况下,三个主节点平分 ```bash Node A: handles slots 0 - 5460 Node B: handles slots 5461 - 10922 Node C: handles slots 10923 - 16383 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值