转载自http://www.jiacheo.org/blog/174
学习分布式, 一致性哈希是最最基础的知识, 所以要理解好.
那什么是一致性哈希呢?(what)
百度百科 上的解释很专业术语. 要一句话定义貌似也有难度: 一致性哈希算法是在哈希算法基础上,提出的在动态变化的分布式环境中,哈希算法应该满足的几个条件: 平衡性, 单调性和分散性.
1.平衡性是指 hash的结果应该平均分配到各个节点, 这样从算法上就解决了负载均衡问题.
2.单调性是指 在新增或者删减节点时, 同一个key访问到的值总是一样的.
3.分散性是指 数据应该分散的存放在 分布式集群中的各个节点(节点自己可以有备份), 不必要每个节点都存储所有的数据.
为什么要一致性哈希?(why)
这个问题问得很好…首先我们要看看不使用一致性hash, 我们的分布式集群如何工作.
1. 普通集群, 把固定的key映射到固定的节点上, 节点只存放各自key的数据, 如图:
这样, 我们必须维护好key和节点的关系, 而且当其中一个节点挂掉了, 节点上的数据可以迁移, 但key的关系也要重新维护.
2. 简单hash集群. 为了不想维护key, 降低复杂性和其他开销, 很容想到 对key进行hash , 然后对节点数取模, 比如我们原本有四个节点, 如下图
这个时候就不必维护这些key对应的node了, 直接通过hash值, 然后对节点数取模, 看起来貌似很完美, 足够了吧?
No! 如果这个时候其中一个节点挂了, 那这个节点的数据就完全不可用了. 当然你会说可以通过数据迁移呀, 嘿嘿, 问题
恰恰难在数据迁移, 因为这时候挂了, 节点数变为3了, 对key取hash后再 mod 3 的话, 大部分的key对应的节点都要改. 这个时候
只能整个集群的数据都重新迁移一遍才能达到效果, 也许你忙完这些工作, 还不如把挂掉的机器换个新的!!! 再者, 不仅仅是节点挂了会出现问题
如果整个分布式集群负载很高, 希望增加节点来解决问题, 这个时候, 迁移的工作还是一样的麻烦, 这样我估计如果数据量庞大的话, 没人敢轻易迁移.
于是便有了一致性hash
3. 一致性哈希
如图, 所有的节点也有自己的key(比如hostname), 经过hash, 然后mod 2的32次方, 映射到这个超大的环上面的一个虚拟节点
然后所有的key去获取value的时候, 也是同样的hash算法, mod 2的32次方, 这时候不一定所有的key都刚好映射到各个节点相应的虚拟
节点上(事实上概率很小), 然后这时候取值只要按照约定好的固定方向(如顺时针), 找到第一个的虚拟节点, 然后根据该虚拟节点
就可以找到相应的node, 然后进行相应的操作.
这个时候, 如果其中一个节点挂了, 那么依然要进行数据迁移, 只不过数据迁移的数据量减少了, 只需要将挂了的节点的数据迁移到他顺时针的下一个
节点上即可, 这个对应的keys依然能够找到数据. 同样的, 如果增加节点, 数据迁移量也不多, 只需要将该节点逆时针方向到达上一个节点之前的key对应的数据都
迁移到新增的节点上就OK了.这就是传说中的一致性哈希.
比如上图, key1 key2 key3 key4 key5 key6的值将由 node2返回( 假设这是一个key value存储集群)
同样的, key7~key11 对应 node3
key12 ~key17对应node4
key18~key22 对应node1
3. 讲完了what和why, 就是how了
其实上面在why讲解过程中, how的部分已经讲解了一大片, 其实关键的地方还是在hash算法的选择, 如何选择好的hash算法, 让他能够平均地分配每个节点, 这才是
最大的问题.
简单的话可以使用MD5算法来作为hash算法, 对于各个hash算法的比较, 可以参考下面的文章
http://www.iteye.com/topic/346682
另外参考 http://www.cnblogs.com/liunx/archive/2010/03/24/1693925.html
和这篇 http://blog.csdn.net/x15594/archive/2011/03/23/6270242.aspx
他们的图画的比我生动