`

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

 
阅读更多

首先分析一下Java client 启动时的部分代码

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

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

Java代码
  1. SockIOPoolpool=SockIOPool.getInstance(poolname);
  2. pool.setServers(servers);
  3. pool.setWeights(weights);
  4. pool.setInitConn(initConn);
  5. pool.setMinConn(minConn);
  6. pool.setMaxConn(maxConn);
  7. pool.setMaxIdle(maxIdle);
  8. pool.setMaxBusyTime(maxBusyTime);
  9. pool.setMaintSleep(maintSleep);
  10. pool.setSocketTO(socketTO);
  11. pool.setSocketConnectTO(socketConnectTO);
  12. pool.setNagle(nagle);
  13. pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
  14. pool.initialize();
  15. MemCachedClientclient=newMemCachedClient(poolname);



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

然后看一下 pool.initialize() 做了什么

Java代码
  1. availPool=newHashMap<String,Map<SockIO,Long>>(servers.length*initConn);
  2. busyPool=newHashMap<String,Map<SockIO,Long>>(servers.length*initConn);
  3. deadPool=newIdentityHashMap<SockIO,Integer>();
  4. hostDeadDur=newHashMap<String,Long>();
  5. hostDead=newHashMap<String,Date>();
  6. maxCreate=(poolMultiplier>minConn)?minConn:minConn/poolMultiplier;//onlycreateuptomaxCreateconnectionsatonce
  7. if(log.isDebugEnabled()){
  8. log.debug("++++initializingpoolwithfollowingsettings:");
  9. log.debug("++++initialsize:"+initConn);
  10. log.debug("++++minspare:"+minConn);
  11. log.debug("++++maxspare:"+maxConn);
  12. }
  13. //ifserversisnotset,oritempty,then
  14. //throwaruntimeexception
  15. if(servers==null||servers.length<=0){
  16. log.error("++++tryingtoinitializewithnoservers");
  17. thrownewIllegalStateException("++++tryingtoinitializewithnoservers");
  18. }
  19. //initalizeourinternalhashingstructures
  20. if(this.hashingAlg==CONSISTENT_HASH)
  21. populateConsistentBuckets();
  22. else
  23. populateBuckets();


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

hash算法共有4种

Java代码
  1. //nativeString.hashCode();
  2. publicstaticfinalintNATIVE_HASH=0;
  3. //originalcompatibilityhashingalgorithm(workswithotherclients)
  4. publicstaticfinalintOLD_COMPAT_HASH=1;
  5. //newCRC32basedcompatibilityhashingalgorithm(workswithotherclients)
  6. publicstaticfinalintNEW_COMPAT_HASH=2;
  7. //MD5Based--Stopsthrashingwhenaserveraddedorremoved
  8. publicstaticfinalintCONSISTENT_HASH=3;



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

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

Java代码
  1. this.buckets=newArrayList<String>();
  2. for(inti=0;i<servers.length;i++){
  3. if(this.weights!=null&&this.weights.length>i){
  4. for(intk=0;k<this.weights[i].intValue();k++){
  5. this.buckets.add(servers[i]);
  6. if(log.isDebugEnabled())
  7. log.debug("++++added"+servers[i]+"toserverbucket");
  8. }
  9. }
  10. else{
  11. this.buckets.add(servers[i]);
  12. }
  13. //createinitialconnections
  14. for(intj=0;j<initConn;j++){
  15. SockIOsocket=createSocket(servers[i]);
  16. if(socket==null){
  17. break;
  18. }
  19. addSocketToPool(availPool,servers[i],socket);
  20. }
  21. }



假如我们设置的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存放对象时会调用

Java代码
  1. SockIOPool.SockIOsock=pool.getSock(key,hashCode);



看一看pool.getSock的代码

Java代码
  1. //getinitialbucket
  2. longbucket=getBucket(key,hashCode);
  3. Stringserver=(this.hashingAlg==CONSISTENT_HASH)
  4. ?consistentBuckets.get(bucket)
  5. :buckets.get((int)bucket);



其中有段代码是这样的,看看getBucket

Java代码
  1. privatelonggetBucket(Stringkey,IntegerhashCode){
  2. longhc=getHash(key,hashCode);
  3. if(this.hashingAlg==CONSISTENT_HASH){
  4. returnfindPointFor(hc);
  5. }
  6. else{
  7. longbucket=hc%buckets.size();
  8. if(bucket<0)bucket*=-1;
  9. returnbucket;
  10. }
  11. }



先不管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。

 

原文地址:http://bachmozart.javaeye.com/blog/211836

分享到:
评论

相关推荐

    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