用于一致性散列的C库源代码简介。
什么是libconhash
libconhash是一个一致的哈希库,可以在Windows和Linux平台上编译,具有以下功能:
- libconhash高性能且易于使用,它使用红黑树来管理所有节点以实现高性能。
- 默认情况下,它使用MD5算法,但它也支持用户定义的哈希函数。
- 易于根据节点的处理能力进行扩展。
一致的散列
为什么需要一致的散列
现在我们将考虑进行负载平衡的常用方法。选择用于缓存对象o的机器号将是:
这里,n是缓存机器的总数。虽然这在您添加或删除缓存机器之前仍然有效:
- 添加缓存机器时,对象o将缓存到机器中:
- 删除缓存计算机时,对象o将缓存到计算机中:
因此,您可以看到几乎所有对象都将散列到一个新位置。这将是一场灾难,因为原始内容服务器被来自缓存机器的请求所淹没。这就是为什么你需要一致的散列。
一致的散列可以保证在删除缓存机器时,只重新缓存其中的对象; 添加新的缓存机器时,只会刷新相当少的对象。
现在我们将逐步进行一致的散列。
哈希空间
通常,哈希函数会将值映射到32位密钥,0~2^<sup>32</sup>-1
。现在想象一下将范围映射到一个圆圈,然后键将被包裹,0将跟随2 ^ 32 -1,如图1所示。
图1
将对象映射到哈希空间
现在考虑四个对象:object1~object4
。我们使用哈希函数来获取它们的键值并将它们映射到圆圈中,如图2所示。
图2
将缓存映射到哈希空间
一致散列的基本思想是使用相同的散列函数将缓存和对象映射到相同的散列空间。
现在考虑我们有三个缓存,A,B和C,然后映射结果如图3所示。
图3
将对象映射到缓存中
现在所有的缓存和对象都被散列到同一个空间中,因此我们可以确定如何将对象映射到缓存中。以物体obj
为例,只需从obj
环形处开始,顺时针转动环,直至找到服务器。如果该服务器已关闭,则转到下一个服务器,依此类推。见上面的图3。
根据该方法,object1
将缓存到缓存A中; object2
并将object3
缓存到缓存C中,并将object4
缓存到缓存B.
添加或删除缓存
现在考虑两种情况,缓存已关闭并被删除; 并添加了一个新的缓存。
如果删除缓存B,则只有在B中缓存的对象将被重新散列并移动到C; 在示例中,请参object4
见图4。
图4
如果添加了新的高速缓存D,并且在环之间object2
和object3
环中对D进行了散列,则只有D和B之间的对象将被重新散列; 在示例中,请参object2
见图5。
图5
虚拟节点
如果没有部署足够的缓存,则可能在缓存之间具有非常不均匀的对象分布。解决方案是引入“虚拟节点”的概念。
虚拟节点是圆圈中缓存点的复制品,每个真实缓存对应于圆圈中的几个虚拟节点; 实际上,每当我们添加缓存时,我们都会在圆圈中创建一些虚拟节点; 当删除缓存时,我们从圆圈中删除其所有虚拟节点。
考虑上面的例子。系统中有两个缓存A和C,现在我们引入虚拟节点,副本为2,然后三个将是4个虚拟节点。缓存A1和缓存A2代表缓存A; 高速缓存C1和高速缓存C2表示高速缓存C,如图6所示。
图6
然后,从对象到虚拟节点的映射将是:
当您获得虚拟节点时,您将获得缓存,如上图所示。
因此,object1和object2被缓存到缓存A中,而object3和object4被缓存到缓存中。结果现在更平衡。
所以现在你知道什么是一致的散列。
使用代码
libconhash的接口
Libconhash非常易于使用。项目中有一个示例,说明如何使用该库。
首先,创建一个conhash实例。然后,您可以添加或删除实例的节点,并查找对象。
更新节点的副本功能尚未实现。
参考
- http://portal.acm.org/citation.cfm?id=258660
- http://en.wikipedia.org/wiki/Consistent_hashing
- http://www.spiteful.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/