简介
一致性哈希可以有效解决分布式存储结构下动态增加和删除节点带来的问题。
传统问题
比如原本的设计一个库30个分表存储用户数据,当查询数据时,根据用户的id%30或者其他的简单的hash算法找到用户数据所在的分表,再去查询用户数据。
但是当数据量陡增,30个分表不够用了,需要增加为80个分表,hash算法也需要改变,也需要做相应的数据迁移,代价很大。
解决方法
将全量缓存空间当成一个环形存储结构,环形空间共有2^32次方个缓存区。
2. 每一个缓存的key都可以对应一个32位的二进制数字,所以对应某一个缓冲区。
3. 我们的每一个缓存节点遵循一样的hash算法,映射到环形空间中。
4. 对应节点和key, 每一个key顺时针方向最近的节点就是key所属的存储节点。
优点
这样设计的好处在哪里呢?
当节点增加或者删除时, 一致性哈希的优势就显现了。
增加节点
当增加缓存节点,整个环形空间的映射规则不改变,一部分key的归属需要作出更改。
如上图,插入新的缓存节点,需要更改key2 缓存不再属于node2, 归属新的节点node4.
删除节点
当某个节点需要删除(或者挂掉),只有少部分的key受到影响。
比如节点3删除。
只有key4发生改变。key4的缓存数据从node3迁移到node1。
这里的数据迁移指的是查询过程中,查询失败,去找顺时针的后继节点。
分布不均匀问题
引入虚拟节点
的概念。
就是基于原来的物理节点映射出N个子节点,将子节点映射到环形空间上。
如上图所示,假如node1的ip是192.168.1.109,那么原node1节点在环形空间的位置就是hash(“192.168.1.109”)。
我们基于node1构建两个虚拟节点,node1-1 和 node1-2,虚拟节点在环形空间的位置可以利用(IP+后缀)计算,例如:
hash(“192.168.1.109#1”),hash(“192.168.1.109#2”)
此时,环形空间中不再有物理节点node1,node2,只有虚拟节点node1-1,node1-2,node2-1,node2-2。由于虚拟节点数量较多,缓存key与虚拟节点的映射关系也变得相对均衡了
参考文献: 程序员小灰