一致性hash算法在Memcache Java client中的应用

Memcache Java Client需要通过应用hash算法来决定内容存放到哪一台memcache服务器,学习了一下http://github.com/gwhalin/Memcached-Java-Client/的源代码,本文记录一下代码里面涉及到的hash算法;

  关于一致性hash,可以看一下http://blog.csdn.net/zhangbinalan/article/details/37889853;

一:代码里面提到了四种hash方法

1:NATIVE_HASH

key.hashCode()

2:OLD_COMPAT_HASH
	private static long origCompatHashingAlg( String key ) {
		long hash   = 0;
		char[] cArr = key.toCharArray();
		for ( int i = 0; i < cArr.length; ++i ) {
			hash = (hash * 33) + cArr[i];
		}
		return hash;
	}


3:NEW_COMPAT_HASH
	//Found to be fast and have very good distribution
	private static long newCompatHashingAlg( String key ) {
		CRC32 checksum = new CRC32();
		checksum.update( key.getBytes() );
		long crc = checksum.getValue();
		return (crc >> 16) & 0x7fff;
	}


4:CONSISTENT_HASH
	private static long md5HashingAlg( String key ) {
		MessageDigest md5 = MD5.get();//MessageDigest.getInstance( "MD5" )
		md5.reset();
		md5.update( key.getBytes() );
		byte[] bKey = md5.digest();
		long res = ((long)(bKey[3]&0xFF) << 24) | ((long)(bKey[2]&0xFF) << 16) | ((long)(bKey[1]&0xFF) << 8) | (long)(bKey[0]&0xFF);
		return res;
	}


二:初始化一致性hash中的"圆圈"

private void populateConsistentBuckets() {
		//TreeMap来存储memcache服务器和它的hash值的对应关系;多个虚拟节点可以对应相同的服务器
		this.consistentBuckets = new TreeMap<Long,String>();
		//不同的memcache服务器可以配置不同的权值
		MessageDigest md5 = MD5.get();
		if ( this.totalWeight <= 0 && this.weights !=  null ) {
			for ( int i = 0; i < this.weights.length; i++ )
				this.totalWeight += ( this.weights[i] == null ) ? 1 : this.weights[i];
		}
		else if ( this.weights == null ) {
			this.totalWeight = this.servers.length;
		}
		for ( int i = 0; i < servers.length; i++ ) {
			int thisWeight = 1;
			if ( this.weights != null && this.weights[i] != null )
				thisWeight = this.weights[i];
			double factor = Math.floor( ((double)(40 * this.servers.length * thisWeight)) / (double)this.totalWeight );
			for ( long j = 0; j < factor; j++ ) {
				byte[] d = md5.digest( ( servers[i] + "-" + j ).getBytes() );
				for ( int h = 0 ; h < 4; h++ ) {
					Long k = 
						  ((long)(d[3+h*4]&0xFF) << 24)
						| ((long)(d[2+h*4]&0xFF) << 16)
						| ((long)(d[1+h*4]&0xFF) << 8)
						| ((long)(d[0+h*4]&0xFF));
					consistentBuckets.put( k, servers[i] );
					if ( log.isDebugEnabled() )
						log.debug( "++++ added " + servers[i] + " to server bucket" );
				}				
			}
		}
	}


三:存入和取出value时如何根据key确定memcache服务器

	//找到第一个大于或者等于hv的那个虚拟节点的hash值
	private Long findPointFor( Long hv ) {
		SortedMap<Long,String> tmap =
			this.consistentBuckets.tailMap( hv );
		return ( tmap.isEmpty() ) ? this.consistentBuckets.firstKey() : tmap.firstKey();
	}

四:实际运行测试一下代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值