一致性HASH算法
在分布式缓存系统中,需要将数据均匀的分布到缓存服务器集群的不同机器上,就需要使用对缓存的数据的key做hash值计算, 然后在将hash值除以服务器节点的数量取模计算出数据需要落到那台服务器节点上。这种算法很简单,也可以实现数据的均匀分布, 但是,增加或者减少数据节点的时候会导致所有缓存数据失效。
传统的取模方式
例如10条数据,3个节点,如果按照取模的方式,那就是
- node a: 0,3,6,9
- node b: 1,4,7
- node c: 2,5,8
当增加一个节点的时候,数据分布就变更为
- node a:0,4,8
- node b:1,5,9
- node c: 2,6
- node d: 3,7
总结:数据3,4,5,6,7,8,9在增加节点的时候,都需要做搬迁,成本太高。
一致性哈希方式
最关键的区别就是,对节点和数据,都做一次哈希运算,然后比较节点和数据的哈希值,数据取和节点最相近的节点做为存放节点。 这样就保证当节点增加或者减少的时候,影响的数据最少。 还是拿刚刚的例子,(用简单的字符串的ascii码做哈希key):
十条数据,算出各自的哈希值
- 0:192
- 1:196
- 2:200
- 3:204
- 4:208
- 5:212
- 6:216
- 7:220
- 8:224
- 9:228
有三个节点,算出各自的哈希值
- node a: 203
- node g: 209
- node z: 228
这个时候比较两者的哈希值,如果大于228,就归到前面的203,相当于整个哈希值就是一个环,对应的映射结果:
- node a: 0,1,2
- node g: 3,4
- node z: 5,6,7,8,9
这个时候加入node n, 就可以算出node n的哈希值:
- node n: 216
这个时候对应的数据就会做迁移:
- node a: 0,1,2
- node g: 3,4
- node n: 5,6
- node z: 7,8,9
这个时候只有5和6需要做迁移
另外,这个时候如果只算出三个哈希值,那再跟数据的哈希值比较的时候,很容易分得不均衡,因此就引入了虚拟节点的概念, 通过把三个节点加上ID后缀等方式,每个节点算出n个哈希值,均匀的放在哈希环上,这样对于数据算出的哈希值, 能够比较散列的分布
通过这种算法做数据分布,在增减节点的时候,可以大大减少数据的迁移规模。
虚拟节点
服务器节点根据hash来分布,有时候会出现不均匀的情况,就会导致数据分布的不均匀, 通过增加虚拟节点,使得服务器节点总数大幅增加,从而散落到hash环上就会更加均匀。