一致性哈希算法(consistent hashing)例子+测试。

一个简单的consistent hashing的例子,很容易理解。

首先有一个设备类,定义了机器名和ip:

public class Cache
{
	public String name;
	public String ipAddress;
}

然后是主要的实现:

public class Shard<T> { 
	//hash 算法并不是保证绝对的平衡,如果 cache 较少的话,对象并不能被均匀的映射到 cache 上,
	//所以增加虚拟节点
	private TreeMap<Long, T> nodes;
	private List<T> shards; //节点碎片
	private final int NODE_NUM = 10; // 每个机器节点关联的虚拟节点个数

	public Shard(List<T> shards) {
		this.shards = shards;
		init();
	}

	private void init() { 
		nodes = new TreeMap<Long, T>();
		for (int i = 0; i < shards.size(); i++) 
		{ // 遍历真实节点
			final T shardInfo = shards.get(i);
			
			for (int n = 0; n < NODE_NUM; n++)
			{
				// 真实节点关联虚拟节点,真实节点是VALUE;
				nodes.put((long) Hash("SHARD-" + i + "-NODE-" + n), shardInfo);
			}
			System.out.println(shardInfo);
		}
	}

	public T getShardInfo(String key) {
		SortedMap<Long, T> tail = nodes.tailMap((long) Hash(key)); 
		if (tail.size() == 0) {
			return nodes.get(nodes.firstKey());
		}
		//找到最近的虚拟节点
		return tail.get(tail.firstKey());
	}
	
	/**
     * 改进的32位FNV算法,高离散
     * 
     * @param string
     *            字符串
     * @return int值
     */
    public static int Hash(String str) 
    {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (byte b : str.getBytes())
            hash = (hash ^ b) * p;
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
        return hash;
    }

}

到这里就完了,是不是很简单,下面来测试下:

public class Test
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		List<Cache> myCaches=new ArrayList<Cache>();
		Cache cache1=new Cache();
		cache1.name="COMPUTER1";
		Cache cache2=new Cache();
		cache2.name="COMPUTER2";
		myCaches.add(cache1);
		myCaches.add(cache2);
		
		
		Shard<Cache> myShard=new Shard<Cache>(myCaches);
		
		Cache currentCache=myShard.getShardInfo("info1");
		System.out.println(currentCache.name);
		
//		for(int i=0;i<20;i++)
//		{
//			String object=getRandomString(20);//产生20位长度的随机字符串
//			Cache currentCache=myShard.getShardInfo(object);
//			System.out.println(currentCache.name);
//		}
		
		
	}
	
	public static String getRandomString(int length) { //length表示生成字符串的长度
	    String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
	    Random random = new Random();   
	    StringBuffer sb = new StringBuffer();   
	    for (int i = 0; i < length; i++) {   
	        int number = random.nextInt(base.length());   
	        sb.append(base.charAt(number));   
	    }   
	    return sb.toString();   
	 }   

}

我们有两台设备,computer1和computer2,第一次初始化要构建一个2的32次方的环,并往上面放设备。这个环由改进的FNV算法实现。位置也由hash算法确定。

但我们只有两台设备,很明显在环上会分布不均匀(这个就不解释了,网上很多资料)。于是我们每台设备增加10个虚拟设备。《一致性哈希算法(consistent hashing)例子+测试。》

最后分布如下:

-1561290727=Hash.Cache@10f11b8, -1083588870=Hash.Cache@10f11b8, -697149481=Hash.Cache@10f11b8, -253517545=Hash.Cache@10f11b8, 397383558=Hash.Cache@10f11b8, 1078505027=Hash.Cache@10f11b8, 1810977445=Hash.Cache@10f11b8, 1844081498=Hash.Cache@10f11b8, 2004894833=Hash.Cache@10f11b8, 2051863688=Hash.Cache@10f11b8

-2147483648到2147483647之间是不是比较均匀,这是java的,如果是c#的就是0~2的32次方。我们hash计算出KEY值为2049553054,然后顺时针找到最近的位置,即为

2051863688=Hash.Cache@10f11b8

结果我们定位到了COMPUTER1

最好我们要看看平衡性如何:取消上面注释的代码,循环20次,得到结果如下:

COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER1
COMPUTER1
COMPUTER2
COMPUTER2
COMPUTER2
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER1
COMPUTER1
COMPUTER2
COMPUTER1
COMPUTER2

大家可以自己取试试,

FNV哈希算法是一种高离散性的哈希算法,特别适用于哈希非常相似的字符串,例如:URL,IP,主机名,文件名等。

以下服务使用了FNV:
1、calc
2、DNS
3、mdbm key/value查询函数
4、数据库索引hash
5、主流web查询/索引引擎
6、高性能email服务
7、基于消息ID查询函数
8、auti-spam反垃圾邮件过滤器
9、NFS实现(比如freebsd 4.3, linux NFS v4)
10、Cohesia MASS project
11、Ada 95的spellchecker
12、开源x86汇编器:flatassembler   user-defined symbol hashtree
13、PowerBASIC
14、PS2、XBOX上的文本资源
15、非加密图形文件指纹
16、FRET
17、Symbian DASM
18、VC++ 2005的hash_map实现
19、memcache中的libketama
20、 PHP 5.x
21、twitter中用于改进cache碎片
22、BSD IDE project
23、deliantra game server
24、 Leprechaun
25、IPv6流标签

    原文作者:哈希算法
    原文地址: https://blog.csdn.net/u014419512/article/details/25681437
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞