当前位置: 代码网 > it编程>数据库>Redis > 大厂面试官问我:Redis为什么使用哈希槽的方式进行数据分片?为什么不适用一致性哈希的方式?【后端八股文十三:Redis 集群哈希八股文合集(1)】

大厂面试官问我:Redis为什么使用哈希槽的方式进行数据分片?为什么不适用一致性哈希的方式?【后端八股文十三:Redis 集群哈希八股文合集(1)】

2024年08月01日 Redis 我要评论
为什么使用一致性哈希? 传统哈希算法(如取模)在节点变更时,会导致大量 key 的重新分布,引发大量的数据迁移和客户端路由更新,容易造成雪崩效应。 而一致性哈希算法通过将节点和 key 都映射到一个虚拟的哈希环上,在节点变更时只需要调整少量 key 的映射关系,减少了数据迁移和客户端路由的开销。

  本文为【redis 集群哈希 八股文合集(1)】初版,后续还会进行优化更新,欢迎大家关注交流~

redis做集群时如何高效快速找到对应的节点 / redis cluster 如何分配命令在哪个节点上执行

哈希槽

原因:

  1. 简单高效:哈希槽是一个 0-16383 的整数范围,通过对 key 进行 crc16 计算后对 16384 取模就可以确定该 key 属于哪个槽。这种方式计算简单高效,且容易管理和维护。
  2. 负载均衡:redis 集群会尽量将 16384 个槽均匀地分配到各个节点上,从而达到良好的负载均衡效果。当集群节点数发生变化时,只需要在节点间进行槽的迁移,不需要重新计算每个 key 的路由。
  3. 扩展性:当集群需要扩展时,可以将部分槽迁移到新加入的节点上,无需对所有 key 进行rehash。这种方式可以平滑地扩展集群规模。

redis为什么使用哈希槽的方式进行数据分片?为什么不适用一致性哈希的方式?/ redis的hash slot算法,与哈希环算法区别

redis 选择使用哈希槽(hash slot)是因为它更加简单高效:

  • 哈希槽是一个 0-16383 的整数范围,通过对 key 进行 crc16 计算后对 16384 取模就可以确定该 key 属于哪个槽。这种方式计算简单高效。
  • 相比之下,一致性哈希需要维护复杂的哈希环拓扑,扩展时需要重新计算所有 key 的路由,不够灵活。
  • 哈希槽可以将 16384 个槽均匀地分配到各个节点上,从而达到良好的负载均衡效果。当集群节点数发生变化时,只需要在节点间进行槽的迁移,不需要重新计算每个 key 的路由。

了解redis的哈希环吗?如何做到哈希一致性?

哈希环(consistent hashing):
redis使用哈希环(consistent hashing)算法来实现哈希一致性。这个算法的核心思想是:

  • 将所有的节点和key都映射到同一个哈希空间(如0-2^32-1)的圆环上。
  • 增加或删除节点时,只影响相邻的节点,其他节点基本不受影响。
  • 这样可以很好地解决增加/删除节点时数据迁移的问题,提高了系统的伸缩性。

什么是哈希环

如上图

  1. 我们有一个虚拟的哈希环,将节点 (node 1、node 2、node 3) 和数据项 (key 1) 都映射到这个环上。
  2. 当我们需要存储一个数据项时,我们会根据该数据项的 hash 值将其定位到哈希环上的某个位置,并将其存储到顺时针方向第一个遇到的节点上
  3. 比如 key 1 被定位到 node3 上
  4. 当我们新增或删除节点时,只需要调整少量数据项的存储位置,而不需要大规模的数据迁移。
  5. 比如如果我们新增了 node 4,那么 key 3 可能会被重新分配到 node 4 上,但其他 key 的存储位置不会受到影响。

具体新增:

比如:

  1. 有三个节点:

    • node 1 位于左上方,占据了大约1/4的环空间。
    • node 2 位于右上方,占据了大约1/4的环空间。
    • node 3 位于中心,占据了剩余的1/2环空间。
  2. 有两个数据项:

    • key 1 位于左上方,接近node 1。
    • key 2 位于右下方,接近node 2。

  1. 有两个节点 node 1 和 node 2,分别存储了 key 1 和 key 2。(根据一致性哈希算法:key 1 被存储在顺时针方向第一个遇到的节点node 1上,key 2 被存储在顺时针方向第一个遇到的节点node 2上)
  2. 现在我们新增了一个节点 node 3。
  3. 为了将 node 3 加入到哈希环中,我们需要重新计算哈希环上的数据分布。
  4. 按照一致性哈希算法的规则,key 1 仍然存储在 node 1 上,因为它距离 node 1 最近。
  5. 但 key 2 原本存储在 node 2 上,现在需要被重新分配。根据一致性哈希算法,key 2 应该被存储在顺时针方向第一个遇到的节点 node 3 上。
  6. 所以经过这次节点变更,只有 key 2 需要被迁移到新的节点 node 3 上,而 key 1 的存储位置保持不变。这就大大减少了数据重分布的开销。

redis 哈希槽的概念?

redis 集群没有使用一致性 hash,而是引入了哈希槽的概念, redis 集群有16384 个哈希槽,每个key 通过 crc16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

哈希槽是如何映射到 redis 实例上的?/ 哈希槽在redis中是如何存储的

节点取余分区。使用特定的数据,如redis的键或用户id,对节点数量n取余:hash(key)%n计算出哈希值,用来决定数据映射到哪一个节点上。

虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=crc16(key)&16383。每一个节点负责维护一部分槽以及槽所映射的键值数据。**redis cluser采用虚拟槽分区算法。

redis哈希槽为什么16384

16384 这个数字是经过权衡后选择的:

  • 16384 是 2^14,是一个比较大的素数,可以较为均匀地分配给集群节点。
  • 16384 个槽够用于大多数应用场景,既不会过于浪费内存,也不会造成过多的槽迁移开销。
  • 使用 16 位 crc16 哈希函数可以快速计算出 key 所属的槽号,计算效率高。

redis一致性哈希是如何用的?怎么判断slot是属于哪个节点。初始化的时候怎么分配的slot的?

一致性哈希的使用:

  • redis 使用一致性哈希算法将所有节点和 key 映射到同一个哈希环上。
  • 当客户端需要查找某个 key 时,会通过哈希函数将该 key 映射到哈希环上的一个点。
  • 然后顺时针查找最近的节点,即可找到负责该 key 的节点。

如何判断 slot 属于哪个节点:

  • redis 将哈希空间分成 16384 个固定大小的槽位(slot)。
  • 每个 key 根据其 key 值经过 crc16 哈希函数计算,得到一个 0-16383 之间的整数值,这个值就是该 key 所在的槽位。
  • 每个 redis 节点负责管理一部分连续的槽位。通过维护一个槽位与节点的映射关系,就可以确定某个槽位属于哪个节点。

初始化时的槽位分配:

  • 在 redis 集群初始化时,会将 16384 个槽位平均分配给集群中的所有节点。
  • 例如,如果集群有 3 个节点,那么每个节点会被分配 0-5460、5461-10920 和 10921-16383 三个槽位区间。
  • 当添加或删除节点时,redis 会根据新的节点数重新计算每个节点应该负责的槽位区间,并自动进行槽位的迁移。

redis集群新增一个节点和删除一个节点后如何解决雪崩现象?

环哈希


为什么使用一致性哈希?

  • 传统哈希算法(如取模)在节点变更时,会导致大量 key 的重新分布,引发大量的数据迁移和客户端路由更新,容易造成雪崩效应。
  • 而一致性哈希算法通过将节点和 key 都映射到一个虚拟的哈希环上,在节点变更时只需要调整少量 key 的映射关系,减少了数据迁移和客户端路由的开销。

cluster 在服务器扩容时如何 rehash,哈希槽如何计算

当增加或减少 redis 集群的节点时,需要对哈希槽进行重新分配,这个过程称为 rehash。

rehash 的具体步骤是:

计算新的哈希槽分配方案

迁移数据到新的槽位

更新客户端路由信息

哈希槽的计算公式是: slot = crc16(key) & 16383

crc16 是一种常用的哈希算法

结果被 16383 取模,得到 0-16383 之间的槽位号

多个主库如何实现

在 redis 中,一般不会存在多个主库的情况,因为这样会导致数据一致性问题。

如果确实有这种需求,可以考虑使用 redis 集群模式,通过哈希槽的方式将数据分散在多个主节点上。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com