普通 hash 算法
在分布式系统中,普通哈希算法通常用于确定数据存储在哪个节点上。例如,如果我们有3个节点,我们可以通过计算hash(key) % 3
来确定一个给定的key
应该存储在哪个节点上。然而,这种方法存在一个显著的问题:当节点数量发生变化(增加或减少)时,会导致大量的缓存数据失效,因为大多数key
的哈希值将会映射到不同的节点上。
一致性 Hash 算法
一致性哈希算法被设计用来减少由于节点增减而导致的缓存失效问题。该算法通过将所有的节点和key
都映射到一个哈希环上,使得每个key
总是被分配给顺时针方向的第一个节点。这样,当节点数量变化时,只有少数key
会受到影响,从而减少了缓存失效的范围。
然而,一致性哈希算法仍然面临一些挑战,例如,当某些key
成为热点时,对应的节点可能会承受过高的负载。为了解决这个问题,有界一致性哈希算法被提了出来。
有界一致性 Hash 算法
有界一致性哈希算法基于 Google 论文《有界一致性哈希算法》(Consistent Hashing with Bounded Loads),可以用于解决一致性哈希环上的缓存热点问题。
算法原理
有界一致性哈希算法的核心思想是在一致性哈希的基础上,根据节点的当前负载情况,为每个节点设置一个最大负载限制。当在一致性哈希环上查找节点时,如果一个节点已经达到了其最大负载限制,则会跳过该节点,继续查找下一个节点。这样可以有效地分散热点key
的负载,避免单个节点过载。
R
: 当前所有节点的总负载(正在处理的总请求数)T
: 节点总个数L
: 当前所有节点的平均负载L = R/T
ε
: 一个参数用于表示在平均负载的基础上能够承受的额外负载上限,可以按照实际需求进行设置M
: 节点的最大负载上限M = L*(1+ε) = R*(1+ε)/T
- 一致性哈希中进行节点查找时,增加检查匹配的节点的负载(正在处理的请求数)是否达到负载上限
M
的操作,如果达到了上限则跳过当前节点继续往后查找。
有界一致性哈希算法结合了最少连接策略和一致性哈希策略的优点,既平衡了负载又保持了一致性哈希的优势。通过调整ε
的值,可以灵活地在最少请求策略和传统一致性哈希策略之间转换
- 当
ε
的值是 0 的时候,就实现了最少连接策略的效果 - 当
ε
的值是无穷大的时候,就是传统的一致性哈希策略
加权有界一致性 Hash 实现
在实际应用中,不同的节点可能具有不同的处理能力,因此需要支持节点权重。加权有界一致性哈希算法通过以下方式实现:
R
: 当前所有节点的总负载(正在处理的总请求数)T
: 所有节点的权重总和L
: 当前所有节点的平均负载(基于权重的平均负载)L = R/T
W
: 当前节点的权重值ε
: 一个参数用于表示在平均负载的基础上能够承受的额外负载上限。M
: 节点的最大负载上限M = W*L*(1+ε) = W*R*(1+ε)/T
在进行节点查找时,如果一个节点的负载达到了其最大负载上限M
,则会跳过该节点,继续查找下一个节点。
Reference
- https://arxiv.org/pdf/1608.01350
- https://medium.com/vimeo-engineering-blog/improving-load-balancing-with-a-new-consistent-hashing-algorithm-9f1bd75709ed
- https://mozillazg.com/2019/02/load-balancing-strategy-algorithm-weighted-least-connection.html
- https://mozillazg.com/2019/04/load-balancing-strategy-algorithm-Consistent-Hashing-with-Bounded-Loads.html