consistent hashing and open-source implementation

一致性哈希要解决的问题很常见:如何将许多键值(譬如md5的值域空间)分布到多个服务器节点。

直接的做法是一个普通的哈希(譬如取模),但如果服务器节点可能会动态变化,每次节点的变化都会导致绝大多数映射的失效,不好。

一致性哈希的做法是,将key的值域看做是一个环,每个服务器映射为多个环上的点(virtual node),所有服务器的点的集合将环分成多个区段,key->server的映射过程是:根据key找到对应的点,然后顺时针(逆时针也行,但要统一顺或者逆)找到最近的虚拟节点,该vnode对应的server,将用来处理这个key。

值得注意的是,一个服务器要映射为多个virtual node(例如100-200个),而且virtual node要均匀分布在环上(要是这100个都挨着,就失去意义了)。考虑一个极端情况,每个服务器都映射为一个vnode,那么某服务器失效的时候,它的负载都被下一台服务器承担去了,失去了均衡负载的效果了。

实践上,还可以根据服务器的能力和当前负载来动态的调整某服务器映射的vnode的个数,以更好地平衡负载。

假设环的空间为md5的值域,即0-2^128-1,实现的时候,要考虑两个hash。

1,server->vnode_list的映射,这可以通过将server的ip地址附加上若干个编号(或随机数),md5以后得到对应的vnode列表。

2,resource_key->ring_key的映射,譬如resource key是URL,那么直接md5就行了。

还要考虑一个区段划分关系,即各个vnode负责的区段是哪些,这用一个二叉树或者数组就行了,查找的时候,对数组进行二分就可以了。

最后就是一个vnode到server的从属关系,也即上面两个hash第一个的逆映射,记录就行了。

consistent hashing在许多互联网平台实现中都是标准的工具,譬如Amazon的Dynamo(参见论文Dynamo: Amazon's Highly Available Key-value Store)。

对于memcache,consistent hashing是在client端做的,可以参见last.fm的实现:http://cn.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients

更多参见wiki条目http://en.wikipedia.org/wiki/Consistent_hashing


posted @ 2011-06-06 23:11  qsort  阅读(375)  评论(0编辑  收藏  举报