突破领导者的限制

突破领导者的限制

问题

假设我们使用 Raft 算法实现了一个 KV 服务。虽然领导者简化了共识协商,但是写请求只能在领导者上处理(如果系统设计要求强一致性,那么读请求也应该由领导者处理),所以集群的接入性能相当于单机。随着业务的发展,系统很容易到达性能瓶颈。

那么,怎么突破领导者的限制呢?方法就是数据分片,即每个集群只负责存储一部分数据。所有集群的数据合起来才是全部数据。

为了方便,以下用节点来代替集群。

那怎么决定哪些数据由哪个节点存储呢?我们需要在客户端和节点之间加一层 Proxy 层:Proxy 层接收客户端的请求,通过对 key 哈希,然后取模来决定由哪个节点来处理该请求。

哈希算法

使用哈希算法,我们是这样切分流量的:假设客户端的请求中有一个 key,Proxy 层接收到请求后,根据下列公式,计算出处理该请求的节点:cluster_index = hash(key) % cluster_num

这种哈希算法优点是简单、快速。但是当节点的数量发生变更时,同一个 key 计算出的节点索引也会变化,导致无法定位到数据。这种情况下,我们就需要迁移数据。迁移数据的成本非常高。例如,从 3 个节点变更为 4 个节点,75% 的数据需要迁移,成本非常高。

一致性哈希算法

我们希望有一种哈希算法:在发生节点数量变更时,迁移尽量少的数据。一致性算法能满足我们的要求。

算法原理

算法原理为:

  • 将一个虚拟圆环分为 2^32 份,按顺时针方向,从 0 开始,直到 2^32 - 1。

  • 使用某种哈希算法,将各个节点映射到圆环上。

  • 当需要对指定的 key 读写时,需要

    • 使用某种哈希算法,计算出 key 在圆环上的位置
    • 沿着顺时针方向找到的第一个节点,就是 key 对应的节点。
GuWw2n.jpg

假设,如果节点 C 故障了,那么只会影响故障节点与其前一个节点间的数据,它们都会被路由到故障节点的下一个节点。

GuhVte.jpg

所以,相比哈希算法,如果使用一致性哈希算法,从 3 个节点变更为 4 个节点,只有 25% 的数据需要迁移,成本为原来的 1/3。

假设,如果新增一个节点 D,那么只会影响新节点与其前一个节点间的数据,它们都会被路由到新节点。

[站外图片上传中...(image-58f87f-1590412658301)]

总的来说,一致哈希算法具有较好的容错性和可扩展性。

虚拟节点

在哈希寻址中,经常会出现这样的问题:客户端请求的 key 比较集中,有的机器负载高,有的机器负载低,那有什么办法使得访问均匀分布吗?答案是虚拟节点

其实,每个节点有多个哈希值分布在虚拟圆环上,并且同一个节点的多个哈希值是相邻的,不会出现交叉的情况。一个哈希值对应一个虚拟节点,并将虚拟节点映射到实际节点。

Gu4w2d.jpg

对比

当节点数量越多时,哈希算法的迁移数量越大,一致性哈希算法的迁移数量越小。使用一致哈希实现哈希寻址时,可以通过增加节点数降低节点宕机对整个集群的影响,以及故障恢复时需要迁移的数据量。

提高 Raft 集群的可用性

在多个 Raft 集群组成的 KV 系统中,如何设计一致哈希,实现当某个集群的节点出现了故障时,整个系统还能稳定运行呢?

答:数据要同时写入当前集群和下一个集群。某个Raft集群挂掉后,原本路由到这个集群的请求,现在都到下一个Raft集群去了。只要下一个Raft集群保存了上一个集群的数据,即使某个集群挂了,整个系统还能正常提供服务。只有两个相邻集群都同时挂掉时,某个集群数据才不能访问。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容