什么是一致性哈希,和通常的分布式哈希表(DHT)有什么区别?通常的DHT使用如下公式进行数据定位:position = Hash(对象名) % N(N是节点个数)。很明显,若是咱们在集群中增减一个节点,都必需要从新计算对象的位置,致使大量的数据迁移的发生。文中的对象表示文件(分布式文件系统)或者数据块(p2p)。而一致性哈希的计算公式则不一样:position = Hash(对象名) % M(M是一个常量,通常取2^31 )。git
如何使用一致性哈希定位文件?github
大致上分红两步:1. 计算节点位置 2. 将对象分布到各个节点。下面,我给各位细细道来:golang
开始时咱们使用经常使用的哈希函数以节点名或者节点IP为键值计算哈希并将计算获得的哈希和M=2^31取模,获得一个新的哈希值。这个哈希值就表示节点的位置。以下图所示咱们以节点名做为键值,计算出N1, N2, N3, N4四个节点的哈希分别是2000, 3000, 4000, 5000。算法
随后,咱们使用相同的方法计算对象的哈希值,hash = Hash(对象名) % (2^31)。计算完成以后获得对象O1的哈希时2100,这时咱们以顺时针的顺序将O1放到节点N2。一样哈希值为3200的O2被放到节点N3。swift
那么这样究竟有什么好处呢?假如咱们增长一个节点X,计算出来X节点的位置是3500。在普通的DHT中咱们须要从新计算每一个节点中的数据的位置。可是(重点来了)在一致性哈希中,咱们只须要把节点N3中的对象O2迁移到新节点X中。只影响到节点N3到节点X之间的对象,图中用黑色粗体标注的部分。大大减小了被影响的节点。负载均衡
咱们在看看删除节点的状况,假如咱们删除节点N3。只须要按照顺时针的方向,将N3中的全部对象迁移到离其最近的节点N4。分布式
能够看到做为一种分布式环境下的数据分布手段,一致性哈希即保留了DHT的负载均衡的特色,又下降了节点的横向拓展带来的数据迁移的开销。那么哪里都用到了一致性哈希?目前我知道的领域有BT下载,分布式文件系统(IPFS,ceph,openstack swift)。函数
从上面的内容咱们能够看到,当咱们在增长或者删除一个节点时,会增长其相邻节点的负载,这固然不是咱们想看到的,理想的状态是将负载均衡到集群中的每个节点。那么应该怎么才能作到这一点呢?能够经过引入虚拟节点来解决这个问题。post
每一个物理节点都被分割为几个虚拟节点,每一个对象先计算其位于哪个虚拟节点,在经过判断虚拟节点的owner,将对象存储到实际的物理节点。spa
从上图能够看到,整个结构分红两层,外层的虚拟节点层和内层的物理节点层,而且外层的虚拟节点是随机分布的。虚拟节点经过这种随机的排列顺序进一步提升了物理节点的负载均衡。
咱们来看看去掉N4节点时的数据迁移状况。当移除N4节点时,全部属于N4的虚拟节点上的数据都要迁移到它们的顺时针方向的下一个虚拟节点,本例中是N3#1,N2#2,N1#3,N1#1。能够看到N4的数据会均衡的再分布到其他的每个节点。
代码已经放到github,使用golang来编写,目前还没有完成,欢迎你们指正。https://github.com/DennisWong/ConsistentHash.git
一致性Hash(Consistent Hashing)原理剖析,关于虚拟节点的解释很易懂
https://blog.csdn.net/lihao21/article/details/54193868
五分钟看懂一致性哈希算法
http://www.javashuo.com/article/p-azvvvvyo-cc.html
介绍openstack的一致性哈希