File tree Expand file tree Collapse file tree 1 file changed +44
-0
lines changed Expand file tree Collapse file tree 1 file changed +44
-0
lines changed Original file line number Diff line number Diff line change 1
1
<h3 style =" padding-bottom :6px ; padding-left :20px ; color :#ffffff ; background-color :#E74C3C ;" >一致性哈希:变化世界中的负载平衡</h3 >
2
2
3
+ Teradata在1986年发布的分布式数据库中使用了这种技术,但他没有提出这个术语。直到1997年,由David Karger等人在应用于分布式缓存问题中提出了 ** “一致性哈希”** ,作为一种在不断变化的Web服务器集群中分配请求的方法。一致性哈希算法也是负载均衡算法中的一种。常用的负载均衡算法适用于集群,但不一定适用于分布式。
4
+
5
+
6
+
7
+ #### 案例背景
8
+
9
+ 在某大促活动中,我们需要将1亿用户数据缓存到1000个Redis实例中,每个Redis实例均摊10万用户数据。通常使用哈希算法(hash(K) mod N )来做映射,先计算用户id的哈希值,然后模运算计算出对应的服务器,最后把对应的数据缓存到对应的服务器即可。此种方法比较简单,但存在一个问题,它不适用于分布式下节点宕机、扩容和缩容的场景。
10
+
11
+ ![ 未命名1550461043.png] ( https://i.loli.net/2019/02/18/5c6a287f117fc.png )
12
+
13
+ 假如1号Redis服务宕机,对应10万用户将无法命中缓存。当然1号Redis服务可以做成高可用集群,但又不适用于分布式缓存下节点的扩容与缩容。试想,大促活动结束后,服务器的压力也会减少,没必要使用这么多服务器,可以将1000个Redis实例缩容为100个。随着节点的宕机、扩容和缩容,势必会带来数据的再哈希与重分配。如此海量的数据,将导致缓存服务不可用。
14
+
15
+
16
+
17
+ #### 一致性哈希算法
18
+
19
+ 为了解决上述问题,一致性哈希算法孕育而出
20
+
21
+ ![ 图1] ( https://i.loli.net/2019/02/18/5c6a7ecbcab93.png )
22
+
23
+ 首先将分配 $2^{32}$ 个槽,也就是从 0 到 $2^{32}-1$ ,如上图,虚拟出环形。通过哈希算法 ` hash(ip, port) ` 计算出Redis实例对应的哈希值,然后对 $2^{32}$ 取模,得到映射到环上的值。对于请求来说,先计算出key的哈希值,同样对 $2^{32}$ 取模,得到映射到环上的值。沿着顺时针匹配第一个Redis服务节点。
24
+
25
+ 当添加Redis节点时,也是通过哈希算法 ` hash(ip, port) ` 计算出Redis实例对应的哈希值,然后对 $2^{32}$ 取模,得到映射到环上的值。假设如下图的X节点:
26
+
27
+ ![ 图2] ( https://i.loli.net/2019/02/18/5c6a855193525.png )
28
+
29
+ 在数据重分配上,仅仅需要将 B节点 和 C节点 之间的数据再哈希、重分配就可以了,B-X之间的数据映射到X节点,X-C之间的数据映射到C节点。这样就避免将全量的数据再哈希、重分配节点。
30
+
31
+
32
+
33
+ ##### 数据倾斜
34
+
35
+ ![ 图3] ( https://i.loli.net/2019/02/18/5c6a872f8a386.png )
36
+
37
+ 如果节点较少,就会造成节点分布不均衡(数据倾斜)的问题,如上图,B-A之间映射的请求远多于A-B之间。就会造成A节点压力增加,而B节点负载较轻。
38
+
39
+
40
+
41
+ #### 虚拟节点
42
+
43
+ ![ 图4] ( https://i.loli.net/2019/02/18/5c6a8b15e7d81.png )
44
+
45
+ 为了解决上述的数据倾斜问题,在一致性哈希算法的基础上引入虚拟节点。其思想是,预先分配N个虚拟节点,然后这些虚拟节点再在映射实际节点,能保证虚拟节点映射的数据,不会过于倾斜。图4中,虚拟节点A1和A2对应的服务器为A、虚拟节点B1和B2对应的服务器为B,以此类推。假如A服务器宕机后,虚拟节点B1和B2则无法映射实际服务器,那么可以将数据按照瞬时间就近映射。D2-B1之间的数据映射到节点C1,实际映射的服务器是C;A1-B2之间的数据映射到节点A2,实际映射的服务器是A,这样就避免数据过度倾斜。
46
+
You can’t perform that action at this time.
0 commit comments