一致性hash算法的实现

一致性hash算法的实现
2014-01-21       0  个评论    来源:只是希望编程越来越有趣  
收藏     我要投稿

1.hashCode的计算,字符串hash算法

有很多hash算法,字符串hash需要达到的两个目标就是冲突要少,也就是分散和考虑到每个字符

参考:字符串hash分析

JDK中使用的累乘因子为31的BKDRHash算法,这是一个经验数字,具有相对比较好的效率和分散。暴雪使用的hash算法主要是针对效率的。

为了尽量发散,使用JDK中HashMap的方法。

    public int hash(String str) {
        if(str == null)
        	return 0;
        int h = 0;
        h ^= str.hashCode();
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
2.一致性Hash的思想

假如现在是客户需要服务器来服务,但是有多个服务器,需要选择一个,客户hash后得到一个int型的数h,但是现在只有n个服务器,怎么来选择服务器呢?

传统的取余方法是:h%n 得到一个小于n的数,再对应是那一个服务器就行。

但是这样带来一个很严重的问题,扩展性。当需要添加一个服务器时(或者崩溃),重新计算h%(n+1),其中有些客户端就需要变更服务器。这将会给系统带来很多不必要的损失。

所以一致性Hash就是为了生存在动态服务器内的。

首先求出服务器的哈希值, 并将其配置到0~2^32的圆上。 然后用同样的方法求出客户端的哈希值,并映射到圆上。 然后从数据映射到的位置开始顺时针查找,第一个服务器服务它。 如果超过2^32找不到服务器,就会保存到第一台服务器上。

使用虚拟节点的思想,为每个服务器在圆上分配100~200个点。这样就能抑制分布不均匀, 最大限度地减小服务器增减时的缓存重新分布。

//C为client客户端,S为service服务器
public class ConsistentHash {
	//虚拟节点的个数,默认200
	private int virtualNum;
	private long unit;//移动
	//存储服务器的容器
	private TreeMap map = new TreeMap<>();
	public ConsistentHash() {
		this(200);
	}
	public ConsistentHash(int virtualNum) {
		this.virtualNum = virtualNum;
		unit = ((long)(Integer.MAX_VALUE/virtualNum)<<1)-2;
	}
	//添加服务器结点
	public void add(S s){
		int hash = hash(s);
		//保证分散到Integer的范围内
		for (int i = 0; i < virtualNum; i++) 
			map.put((int)(hash+i*unit), s);
	}
	//删除服务器结点
	public void remove(S s){
		int hash = hash(s);
		//保证分散到Integer的范围内,先转换为int再转换为Integer
		for (int i = 0; i < virtualNum; i++) 
			map.remove((Integer)(int)(hash+i*unit));
	}
	//获取服务器
	public S get(C c){
		if(map.isEmpty())
			return null;
		int hash = hash(c);
		//TreeMap独有的取上和取下方法
		//ceiling 和 floor (Math中是ceil)
		Entry entry = map.ceilingEntry(hash);
		if(entry == null) //空就代表需要回环了
			return map.firstEntry().getValue();
		else
			return entry.getValue();
	}
	//再次分散的hash方法
	private int hash(Object o) {
        if(o == null)
        	return 0;
        int h = 0;
        h ^= o.hashCode();
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值