`
bachmozart
  • 浏览: 110092 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Memcached 集群,客户端自动Hash到不同服务器的实现

    博客分类:
  • Java
阅读更多
.....
首先分析一下Java client 启动时的部分代码

Memcached 支持直接设置多个servers属性 来实现多个memcahced均衡,对应还有一个属性是weights,字面意思就是权重,分析了一下代码,和我想的是一样的

启动memcached的代码通常是这样的

SockIOPool pool = SockIOPool.getInstance(poolname);
pool.setServers(servers);
pool.setWeights(weights);
pool.setInitConn(initConn);
pool.setMinConn(minConn);
pool.setMaxConn(maxConn);
pool.setMaxIdle(maxIdle);
pool.setMaxBusyTime(maxBusyTime);
pool.setMaintSleep(maintSleep);
pool.setSocketTO(socketTO);
pool.setSocketConnectTO(socketConnectTO);
pool.setNagle(nagle);
pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
pool.initialize();
MemCachedClient client = new MemCachedClient(poolname);


servers 和 weights 都是一个数组,就是说可以同时设置多个server

然后看一下 pool.initialize() 做了什么
availPool   = new HashMap<String,Map<SockIO,Long>>( servers.length * initConn );
busyPool    = new HashMap<String,Map<SockIO,Long>>( servers.length * initConn );
deadPool    = new IdentityHashMap<SockIO,Integer>();
hostDeadDur = new HashMap<String,Long>();
hostDead    = new HashMap<String,Date>();
maxCreate   = (poolMultiplier > minConn) ? minConn : minConn / poolMultiplier;	// only create up to maxCreate connections at once
if ( log.isDebugEnabled() ) {
	log.debug( "++++ initializing pool with following settings:" );
	log.debug( "++++ initial size: " + initConn );
	log.debug( "++++ min spare   : " + minConn );
	log.debug( "++++ max spare   : " + maxConn );
}
// if servers is not set, or it empty, then
// throw a runtime exception
if ( servers == null || servers.length <= 0 ) {
	log.error( "++++ trying to initialize with no servers" );
	throw new IllegalStateException( "++++ trying to initialize with no servers" );
}
	// initalize our internal hashing structures
        if ( this.hashingAlg == CONSISTENT_HASH )
		populateConsistentBuckets();
	else
	        populateBuckets();

看到这里就是开辟一些连接池的空间,然后调用了根据我们选择的hash 算法 执行populateBuckets();或者populateConsistentBuckets();

hash算法共有4种
// native String.hashCode();
public static final int NATIVE_HASH     = 0;	
// original compatibility hashing algorithm (works with other clients)
public static final int OLD_COMPAT_HASH = 1;
// new CRC32 based compatibility hashing algorithm (works with other clients)	
public static final int NEW_COMPAT_HASH = 2;
// MD5 Based -- Stops thrashing when a server added or removed
public static final int CONSISTENT_HASH = 3;		


我们通常用的是 NEW_COMPAT_HASH,这个保证可以wokrs with other clients

所以看一下populateBuckets()做了什么

this.buckets = new ArrayList<String>();
for ( int i = 0; i < servers.length; i++ ) {
  if ( this.weights != null && this.weights.length > i ) {
     for ( int k = 0; k < this.weights[i].intValue(); k++ ) {
	 this.buckets.add( servers[i] );
	 if ( log.isDebugEnabled() )
	    log.debug( "++++ added " + servers[i] + " to server bucket" );
     }
  }
  else {
     this.buckets.add( servers[i] );
  }
     // create initial connections
  for ( int j = 0; j < initConn; j++ ) {
          SockIO socket = createSocket( servers[i] );
	  if ( socket == null ) {
		break;
          }
          addSocketToPool( availPool, servers[i], socket );
  }
}


假如我们设置的servers是 192.168.0.1:44444和192.168.0.2:22222
然后我们设置了weights是  5和3 那么
buckets list的值最终会是
[
192.168.0.1:44444,
192.168.0.1:44444,
192.168.0.1:44444,
192.168.0.1:44444,
192.168.0.1:44444,
192.168.0.2:22222,
192.168.0.2:22222.
192.168.0.2:22222.
]
然后就开始根据initCon初始连接数按servers分别创建socket
那么究竟这个buckets做什么用呢?

在我们使用set存放对象时会调用

SockIOPool.SockIO sock = pool.getSock( key, hashCode );


看一看pool.getSock的代码

// get initial bucket
long bucket = getBucket( key, hashCode );
String server = ( this.hashingAlg == CONSISTENT_HASH )
		? consistentBuckets.get( bucket )
		: buckets.get( (int)bucket );


其中有段代码是这样的,看看getBucket
private long getBucket( String key, Integer hashCode ) {
	long hc = getHash( key, hashCode );
	if ( this.hashingAlg == CONSISTENT_HASH ) {
		return findPointFor( hc );
	}
	else {
	     long bucket = hc % buckets.size();
		if ( bucket < 0 ) bucket *= -1;
			return bucket;
	}
}


先不管key和hashCode,我们看到首先算出一个hc值后会直接做hc%buckets.size()实际上就是根据buckets的数量散列,最终值一定是buckets.size()范围里的一个值
然后最终server值就根据buckets.get( (int)bucket )得到,那么假如我们得到bucket是3,则参照上面buckets 里的值,得到 list.get(3)=192.168.0.1:44444 所以会根据weight设置的值的不同得到不同的server ,如果 weights设置10:1 那buckets里就是10个相同的server和另一个不同的,将来散列得到的server很大可能性是servers里设置的第一个server。






8
5
分享到:
评论

相关推荐

    Redis 服务器管理(集群主从复制及高可用)

    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更...

    java开源包3

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包4

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包1

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包11

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包2

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包6

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包5

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包10

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包8

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包7

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包9

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包101

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    Java资源包01

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    JAVA上百实例源码以及开源项目

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA上百实例源码以及开源项目源代码

    Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多...

Global site tag (gtag.js) - Google Analytics