接上文《memcache-client-forjava 源码分析之DefaultCacheImpl分析》,主要分析ICache另外一个针对Memcached缓存实现,重点实现了memcached的高可用能力。

由于底层访问复用了java_memcached-release包的实现,memcache-client-forjava只是在上层做了简单封装。本文重点分析下如何进行的封装,以提高自己的设计经验。个人认为,java_memcached-release源码阅读,比spymemcached更简单容易。spymemcached底层使用NIO,selector实现复用。而java_memcached-release使用的是pool技术实现复用。

要实现memcached高可用,重点注意以下方面

  1. node节点与key的对应关系

  2. node节点之间的数据复制

  3. node节点心跳探测

  4. cluster元配置信息管理

接下来主要从类图,数据存储,数据读取3个方面简单说明下。

1.整体类图

memcache-client-forjava 源码分析之MemcachedCacheManager_第1张图片

*Config信息:保存着解析XML元数据。在初始化时解析生成。

MemcachedCacheManager:管理元数据,提供IMemcachedCache对象聚集,以及Cluster对象关系数据。

MemcachedCache:操作memcached统一访问入口。

MemCachedClientHelper:处理Cluster与MemCachedClient关系帮助类

MemCachedClient:danga接口,所有Memcached操作均委派到它处理

ClusterProcessor:处理Node数据复制任务

2.启动序列


可以简单分为2部分:1.解析XML到*Config;2.按元数据构造对象。

3. put序列图

memcache-client-forjava 源码分析之MemcachedCacheManager_第2张图片


完成三部分工作

1)确认目标节点

2)保存数据

3)添加数据复制任务到队列。


4.get序列图

memcache-client-forjava 源码分析之MemcachedCacheManager_第3张图片

主要工作内容

1)两次获取。

2)注意,第二次获取,是否从其他节点获取数据,按照standby,active模式会有所区别。

3) 这里的standby模式不是我们理解的含义,被小坑了下。

集群的active和standby两种模式,前者速度可能在某些情况下稍慢(当key的确没有存在于集群任何一节点时,active模式会去尝试两个节点获取数据),但是具有数据恢复功能,后者速度比较快,但是没有数据恢复功能。

5.存疑

public Object get(String key)
{
   Object result = null;
   boolean isError = false;
   
   try
   {
      result = getCacheClient(key).get(key); 
   }
   catch(MemcachedException ex)
   {
      Logger.error(new StringBuilder(helper.getCacheName())
         .append(" cluster get error"),ex);
      
      isError = true;
   }
   
   
   if (result == null && helper.hasCluster())
      if (isError || helper.getClusterMode().equals
            (MemcachedClientClusterConfig.CLUSTER_MODE_ACTIVE))
   {
      List caches = helper.getClusterCache();
      
      for(MemCachedClient cache : caches)
      {
         if (getCacheClient(key).equals(cache))
            continue;
         
         try
         {
            try
            {
               result = cache.get(key);
            }
            catch(MemcachedException ex)
            {
               Logger.error(new StringBuilder(helper.getCacheName())
                  .append(" cluster get error"),ex);
               
               continue;
            }
            //及时恢复宕机节点
            //仅仅判断另一台备份机器,不多次判断,防止效率低下
            if (helper.getClusterMode()
                  .equals(MemcachedClientClusterConfig.CLUSTER_MODE_ACTIVE) && result != null)
            {
               Object[] commands = new Object[]{CacheCommand.RECOVER,key,result};
               
               addCommandToQueue(commands);
            }
            
            break;
            
         }
         catch(Exception e)
         {
            Logger.error(new StringBuilder(helper.getCacheName())
                     .append(" cluster get error"),e);
         }

      }
   }

   return result;
}

6.其他


当然,还提供了统计,恢复功能,就不说了。