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

源码分析Memcached-Java-Client一致性hash算法

 
阅读更多
memcached的分布式主要体现在client端,server之间没有关系。
一致性hash算法:cache不能命中的问题仍然存在,但是只存在于2个节点之间的位置。相对于取模的算法,一致性hash算法除了计算key的hash值外,还会计算每个server对应的hash值,然后将这些hash值映射到一个有限的值域上(比如0~2^32)。通过寻找hash值等于大于hash(key)的最小server作为存储该key数据的目标server。如果找不到,则直接把具有最小hash值的server作为目标server。
源码版本:Memcached-Java-Client-release_2.6.1
1、计算每个server对应的hash值,将值存入treemap 排序模拟圆,主要方法代码入下。
private void populateConsistentBuckets() {
  // store buckets in tree map
  consistentBuckets = new TreeMap<Long, String>();
  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);
      //根据权重控制虚拟节点数量 (factor * 4)。
   for (long j = 0; j < factor; j++) {
    byte[] d = md5.digest((servers[i] + "-" + j).getBytes());
    //192.168.211.240:11212-0 。。。 192.168.211.240:11212-39
//	 System.out.println("server key="+servers[i] + "-" + j);
    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));
     //按Long值从小到大排序
     consistentBuckets.put(k, servers[i]);
    }
   }
   // Create a socket pool for each host
   // Create an object pool to contain our active connections
   GenericObjectPool gop;
   SchoonerSockIOFactory factory;
   if (authInfo != null) {
    factory = new AuthSchoonerSockIOFactory(servers[i], isTcp, bufferSize, socketTO, socketConnectTO,
      nagle, authInfo);
   } else {
    factory = new SchoonerSockIOFactory(servers[i], isTcp, bufferSize, socketTO, socketConnectTO, nagle);
   }
   gop = new GenericObjectPool(factory, maxConn, GenericObjectPool.WHEN_EXHAUSTED_BLOCK, maxIdle, maxConn);
   factory.setSockets(gop);
   socketPool.put(servers[i], gop);
  }
  System.out.println("consistentBuckets="+consistentBuckets);
 }
 输出:
consistentBuckets={7786957=192.168.211.240:11212, 13055238=192.168.211.240:11212, 15819052=192.168.211.240:11211,。。。 4294784513=192.168.211.240:11212}
2、计算存储数据key hash,寻找目标server。
consistentBuckets.get(bucket)
 //计算客户端key hash值
 private static long md5HashingAlg(String key) {
  MessageDigest md5 = MD5.get();
  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);
  System.out.println("key="+key+" hash result="+res);
  return res;
 }
输出:
 key=1 hash result=943901380
 key=2 hash result=2373066440
 
 //查找目标server
 private final Long findPointFor(Long hv) {
  // this works in java 6, but still want to release support for java5
  // Long k = this.consistentBuckets.ceilingKey( hv );
  // return ( k == null ) ? this.consistentBuckets.firstKey() : k;
    //hash值等于大于hash(key)的最小server作为存储该key数据的目标server。
  SortedMap<Long, String> tmap = this.consistentBuckets.tailMap(hv);
  System.out.println("hash result="+hv+" tailMap="+tmap);
  //如果找不到,则直接把具有最小hash值的server作为目标server。
  return (tmap.isEmpty()) ? this.consistentBuckets.firstKey() : tmap.firstKey();
 }
 
输出:
hash result=943901380 tailMap={948021698=192.168.211.240:11212, 973571166=192.168.211.240:11212, 。。。4294784513=192.168.211.240:11212}
 
 
0
0
分享到:
评论

相关推荐

    数据平台缓存技术方案Memcached-Redis[汇编].pdf

    然而,普通一致性哈希算法有潜在的问题是节点 Hash 后会不均匀地分布在环上,解决方案是改善 Hash 算法,均匀分配各节点到环上,使用虚拟节点的思想,为每个物理服务器节点在圆上分配 100~200 个点。 Memcached 的...

    Java开发中的Memcache原理及实现

    MemcachedClient client = new MemcachedClient(new InetSocketAddress("localhost", 11211)); // 存储数据 client.set("myKey", 60, "myValue"); // key存活60秒 // 获取数据 String value = (String) ...

    神级memcached源代码分析文档_1.4.0代码分析

    客户端的哈希算法决定了key如何映射到特定的server,通常采用一致性哈希,以保证server增减时,数据迁移的影响最小化。 总结,通过深入分析Memcached的源代码,我们可以了解到其高效运行背后的设计思想和技术实现,...

    Memcached的封装优化及相关操作api

    - `HashAlgorithm`:一致性哈希算法,如KetamaConsistentHash算法。 ### 6. 应用场景 Memcached广泛应用于Web应用的session共享、热门数据缓存、API请求缓存等领域。 通过上述知识点,开发者可以更好地理解和使用...

    pymemcache

    为此,`pymemcache`提供了一种基于一致性哈希算法的选择机制,可以自动将键映射到不同的服务器上,并且能够在某台服务器宕机时自动重新分配负载。 ```python from pymemcache.client.hash import HashClient # ...

    libmemcached

    - **一致性哈希(Consistent Hashing)**: 通过一致性哈希算法,`libmemcached`可以在添加或删除服务器时最小化数据重新分布的影响。 - **缓存失效策略**: 提供了TTL(Time To Live)和LRU(Least Recently Used)等...

    Redis 35 道面试题及答案.docx

    - Redis的操作具有原子性,确保了并发环境下的数据一致性。 - 提供了持久化选项,如RDB(Redis Database Backup)内存快照和AOF(Append Only File)日志,以在系统崩溃后恢复数据。 - 支持主从复制,可实现高...

    人人网技术架构介绍(人人网-黄晶)

    在分区策略上,NuclearRose使用了Hash Ring算法,当节点数量变化时,能够优雅地处理数据迁移,确保系统的稳定运行。 为了保证一致性,NuclearRose采用了类似W+R&gt;N的策略,其中W代表写操作的数量,R代表读操作的数量...

Global site tag (gtag.js) - Google Analytics