好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

memcached客户端操作类

memcached客户端操作类

分享封装好的面向JAVA的memcached客户端操作类

书接上文: 理论加实践,谈谈我对memcached的学习感悟!

接近两周的时间,终于将面向 JAVA 的 memcached 客户端操作类封装写完。
现将当前的成果共享上来,希望有经验的朋友能指点一二。

一、初衷

其实, java_memcached-release 已经很完善了,并且使用起来非常方便
但是个人还是习惯将第三方的lib封装起来,好处有二:首先可以为应用层与底层留下空间,增加灵活性;另外也可以根据具体的项目要求,对方法进行重载,增加友好性。
在对 java_memcached-release 进行封装之前,有以下几个主要目的:

支持配置文件 ,包括定义 memcached 服务器信息及连接池相关的初始化参数。这对于一个项目来说,是必须的,否则一旦对 memcached 服务器进行调整,或者需要改变连接池的某个参数,还要去修改JAVA文件,再重新编译、打包,那就太儿戏了。
第一次对工具类进行初始化时,要 对预先配置的各服务器进行检测 ,如果无法连接,或者连接时间超过上限,则 放弃该服务器 。在 java_memcached-release 中,使用 pool.setServers(String[]{" ServerA_IP:Port ", " ServerB_IP:Port "}) 方式传入备用的服务器信息,如果其中某个服务器无法连接,或连接时间过长,那么每次对该服务器进行操作时(比如: add ),会 等待相对长的时间 ,由于 memcached 内部采用分布式算法,并不是每次操作都会将任务指派给这台服务器,但偶尔一次漫长的等待还是非常不爽的,更与使用内存数据库的初衷产生强烈反差。
是否启用memcached的开关 :这个也很主要,首先可以针对两种情况对性能进行监控和对比,另外在生产环境下,对项目进行调试时,为了数据的一致性,也需要暂时关闭内存数据库支持,待问题排除后再重新打开。
返回当前 各服务器运行状态的统计信息 ,源生的stats方法很全面,但输出的参数顺序很不适应,如果能显示中文就更好了,因为日后的项目维护人员不一定能了解每个英文参数的确切含义。
可以按服务器和Slab 对其中的item进行遍历 ,然后可以对选定的item进行查询或者删除。虽说这种操作不被推荐,但在对项目进行Debug时还是非常需要的
按照习惯对某些方法进行重载,比如add,源生的超期参数是Date,但有些时候还是感觉传入一个天数更方便一些。
满足一定性能要求的构造方式以及初始化逻辑

在进行封装时,完全遵循了以上的七个原则,至于最后一条,还需要等待时间去验证

二、依赖

memcached-1.2.1-win32 ( memcached.exe ) 最主要的 com.danga.MemCached ( java_memcached-release_2.6.6.jar )  最关键的,面向JAVA的memcached客户端lib org.dom4j ( dom4j-1.6.1.jar )  用于加载并解析配置文件(xml格式) org.apache.commons.net.telnet ( commons-net-3.2.jar )  使用Telnet方式对服务器进行检测,以确认是否可用

如果想要 memcached 的支持自动压缩功能,也可以使用 java_memcached-release_1.6.jar ,其用法与 2.6.6 全部一致,但不要同时使用这两个版本,以免发生意外问题。

三、配置文件

文件名称: MemCachedConfig.xml
存放位置: src/
文件内容:

  <?  xml version="1.0" encoding="UTF-8"  ?> 

 <!--   

 *****  memcached数据库配置文件  *****
 
 author : 网无忌(netwild)
 email  : inetwild@gmail.com
 qq     : 52100641
     
 ***********************************
  --> 

 <  MemCachedConfig  > 

     <!--   
    Enabled : 是否启用memcached内存数据库选项
    可选值 : true - 启用; false - 停用
      --> 
     <  Enabled  > true </  Enabled  > 
    
     <!--   
    Servers : 可用的memcached服务器列表,各服务器根据weight(负载权重值)实现分布式任务均衡
    注意 : 各memcached服务器负载权重值的最大公约数最好为1,可在一定程度上简化其内部的负载均衡算法
    规则 : <Server host="memcached服务器IP或域名" post="memcached服务端口(默认11211)" weight="负载权重值" />
      --> 
     <  Servers  > 
         <  Server   host  ="192.168.1.10"   post  ="11211"   weight  ="2"   /> 
         <  Server   host  ="192.168.1.11"   post  ="11211"   weight  ="1"   /> 
         <  Server   host  ="192.168.1.12"   post  ="11211"   weight  ="1"   /> 
     </  Servers  > 
    
     <!--   
    Config : memcached数据库配置选项
      initConn : 初始连接数
      minConn : 最小连接数
      maxConn : 最大连接数
      maxIdle : 连接最大空闲时间(毫秒)
      maintSleep : 主线程的维护周期(每隔多少秒维护一次连接池,0表示不启用主线程)
      socketTO : 读取操作的超时限制(毫秒)
      socketConnTO : 连接操作的超时限制(毫秒,0表示不限制)
      compressEnable : 是否启用自动压缩(该参数从java_memcached-release_2.6.1开始不再支持)
      compressThreshold : 超过指定大小(bytes)的数据都会被压缩(该参数从java_memcached-release_2.6.1开始不再支持)
      --> 
     <  Config  > 
         <  property   name  ="initConn"  > 5 </  property  > 
         <  property   name  ="minConn"  > 5 </  property  > 
         <  property   name  ="maxConn"  > 250 </  property  > 
         <  property   name  ="maxIdle"  > 21600000 </  property  > 
         <  property   name  ="maintSleep"  > 30 </  property  > 
         <  property   name  ="socketTO"  > 10000 </  property  > 
         <  property   name  ="socketConnTO"  > 0 </  property  > 
         <  property   name  ="compressEnable"  > true </  property  > 
         <  property   name  ="compressThreshold"  > 65536 </  property  > 
     </  Config  > 
 </  MemCachedConfig  >  

四、封装好的memcached客户端操作类

文件名称: MemCached.java
存放位置: src.com.common
文件内容:

  package   com.common;

  import   java.io.File;
  import   java.text.DecimalFormat;
  import   java.util.ArrayList;
  import   java.util.Calendar;
  import   java.util.LinkedList;
  import   java.util.List;
  import   java.util.Date;
  import   java.util.HashMap;
  import   java.util.LinkedHashMap;
  import   java.util.Map;

  import   org.apache.commons.net.telnet.TelnetClient;
  import   org.dom4j.Document;
  import   org.dom4j.Element;
  import   org.dom4j.Node;
  import   org.dom4j.io.SAXReader;

  import   com.danga.MemCached.MemCachedClient;
  import   com.danga.MemCached.SockIOPool;

  /**  
 * @category   memcached内存数据库操作类
 *   @author       网无忌(netwild)
 * @email      inetwild@gmail.com
 * @qq         52100641
 *   @version      1.0
   */ 
 public   class   MemCached {
    
      //  是否启用MemCached内存数据库 
     protected   static   boolean  enUsed =  true  ;
    
      //  创建全局唯一的可实例化对象 
     protected   static  MemCached memCached =  new   MemCached();
    
      //  初始化MemCached客户端对象 
     protected   static  MemCachedClient memClient =  new   MemCachedClient();
    
      //  定义MemCached服务器运行环境配置文件名称 
     private   static   final  String MemCachedConfigFile_NAME = "MemCachedConfig.xml" ;
    
      //  定义可用的MemCached服务器列表,用于分布式存储 
     private   static  String[] serverListArr =  new  String[1 ];
    
      //  定义各MemCached服务器的负载权重列表,与服务器列表按先后顺序对应 
     private   static  Integer[] weightListArr =  new  Integer[1 ];;
    
      //  定义MemCached服务器运行环境表,配置文件中关于参数相关数据将保存到该表 
     private   static  Map<String, String>  serverConfig;
    
      //  定义MemCached服务器运行状态表,用于保存各状态的中文解释 
     protected   static  HashMap<String, String>  statsItems;

      //  设置全局静态参数,以下代码在整个服务器运行周期内仅运行一次! 
     static   {
        
          //  初始化MemCached运行环境配置
          //  首先初始化各参数默认值,然后加载配置文件,遍历其中的参数值并进行覆盖。 
         initConfig();

          if (enUsed){  //  如果已启用memcached缓存服务
              //  获取socke连接池的实例对象 
            SockIOPool pool =  SockIOPool.getInstance();
    
              //  设置可用的MemCached服务器信息,实现分布式存储 
             pool.setServers(serverListArr);
            
              //  设置各MemCached服务器的负载权重,根据可支配内存实现负载均衡 
             pool.setWeights(weightListArr);
    
              //  设置初始连接数 
            pool.setInitConn(Integer.parseInt(serverConfig.get("initConn" ).toString()));
            
              //  设置最小连接数 
            pool.setMinConn(Integer.parseInt(serverConfig.get("minConn" ).toString()));
            
              //  设置最大连接数 
            pool.setMaxConn(Integer.parseInt(serverConfig.get("maxConn" ).toString()));
            
              //  设置连接最大空闲时间 
            pool.setMaxIdle(Long.parseLong(serverConfig.get("maxIdle" ).toString()));
    
              //  设置主线程的睡眠时间,每隔该时间维护一次各连接线程状态 
            pool.setMaintSleep(Long.parseLong(serverConfig.get("maintSleep" ).toString()));
    
              //  关闭nagle算法 
            pool.setNagle( false  );
            
              //  读取操作的超时限制 
            pool.setSocketTO(Integer.parseInt(serverConfig.get("socketTO" ).toString()));
            
              //  连接操作的超时限制,0为不限制 
            pool.setSocketConnectTO(Integer.parseInt(serverConfig.get("socketConnTO" ).toString()));
    
              //  初始化连接池 
             pool.initialize();
    
              //  压缩设置,超过指定大小的数据都会被压缩
              //  从java_memcached-release_2.6.1开始已经不再支持内置的数据压缩功能
              //  memClient.setCompressEnable(Boolean.parseBoolean(serverConfig.get("compressEnable").toString()));
              //  memClient.setCompressThreshold(Long.parseLong(serverConfig.get("compressThreshold").toString())); 
         }
    }
    
      /**  
     * @category 初始化MemCached运行环境配置
     * @category 注:该方法在整个服务器周期内仅运行一次
       */ 
     protected   static   void   initConfig(){
        
          //  初始化可用的MemCached服务器列表默认值(本机) 
        serverListArr[0] = "127.0.0.1:11211" ;
        weightListArr[ 0] = 1 ;
        
          //  初始化MemCached服务器运行环境表(默认值),当某参数未在配置文件中进行定义时,将使用该默认值 
        serverConfig =  new  HashMap<String, String> (){
              private   static   final   long  serialVersionUID = 1L ;
            {
                put( "initConn", "5");  //  设置初始连接数 
                put("minConn", "5");  //  设置最小连接数 
                put("maxConn", "250");  //  设置最大连接数 
                put("maxIdle", "21600000");  //  设置连接最大空闲时间(6小时) 
                put("maintSleep", "30");  //  设置主线程的睡眠时间(30秒) 
                put("socketTO", "10000");  //  读取操作的超时限制(10秒) 
                put("socketConnTO", "0");  //  连接操作的超时限制(不限制) 
                put("compressEnable", "true");  //  是否启用自动压缩(启用) 
                put("compressThreshold", "65536");  //  超过指定大小的数据都会被压缩(64K) 
             }
        };

          //  开始读取配置文件,并将其中的参数值向默认环境表中进行覆盖 
        String filePath = Thread.currentThread().getContextClassLoader().getResource("MemCachedConfig.xml").getPath().substring(1 );
        File file  =  new  File(filePath.replaceAll("%20"," " ));
          try  {
              if (file.exists()){  //  如果可以成功加载配置文件 
                SAXReader sr =  new   SAXReader();
                Document doc  =  sr.read(file);
                Element Root  = doc.getRootElement();  //  获得根节点 
                Element Enabled = (Element)Root.selectSingleNode("Enabled");  //  获得是否启用memcached节点 
                Element Servers = (Element)Root.selectSingleNode("Servers");  //  获得可用的服务器列表父节点 
                Element Config = (Element)Root.selectSingleNode("Config");  //  获得运行环境参数列表父节点 
                enUsed = Boolean.parseBoolean(Enabled.getText());  //  是否启用memcached缓存服务 
                List<Element> serverDoms = Servers.elements();  //  备用的服务器列表 
                List<Element> serverUsed =  new  ArrayList<Element>();  //  经检测,实际可用的服务器列表 
                TelnetClient telnet =  new  TelnetClient();  //  初始化Telnet对象,用来检测服务器是否可以成功连接 
                telnet.setConnectTimeout(5000);  //  连接超时:5秒 
                 for  (Element serverTmp : serverDoms){
                      try  {
                        telnet.connect(serverTmp.attributeValue( "host"), Integer.parseInt(serverTmp.attributeValue("post")));  //  连接到服务器 
                        telnet.disconnect();  //  断开连接 
                        serverUsed.add(serverTmp);  //  连接成功,将服务器添加到实际可用列表 
                    } catch  (Exception e){}
                }
                  int  serverCount = serverUsed.size();  //  经检测,实际可用的服务器个数 
                 if (serverCount == 0){  //  没有发现实际可用的服务器,返回 
                    enUsed =  false  ;
                      return  ;
                }
                serverListArr  =  new  String[serverCount];  //  初始化服务器地址及端口号数组 
                weightListArr =  new  Integer[serverCount];  //  初始化服务器负载权重数组 
                 for ( int  ind=0; ind < serverCount; ind++){  //  向服务器数组进行赋值 
                    serverListArr[ind] = serverUsed.get(ind).attributeValue("host") + ":" + serverUsed.get(ind).attributeValue("post" );
                    weightListArr[ind]  = Integer.parseInt(serverUsed.get(ind).attributeValue("weight" ).toString());
                }
                Object[] serverConfigArr  = serverConfig.keySet().toArray();  //  返回服务器运行环境参数列表,用于遍历配置文件 
                 for  (Object cfgItem : serverConfigArr){
                    Node node  = Config.selectSingleNode("//property[@name='" + cfgItem + "']");  //  查找指定的参数节点 
                     if (node ==  null )  continue ;  //  如果该参数节点不存在,则继续查找下一个参数,该参数将采用默认值 
                    Element configNode =  (Element)node;
                    serverConfig.put(cfgItem.toString(), configNode.getTextTrim());   //  添加配置文件中定义的参数值 
                 }
            }
        }  catch  (Exception e){
            System.out.println(e.toString());
        }

          //  初始化MemCached服务器运行状态表,对各状态进行中文解释 
        statsItems =  new  HashMap<String, String> (){
            {
                put( "pid", "MemCached服务进程ID" );
                put( "version", "MemCached服务版本" );
                put( "pointer_size", "MemCached服务器架构" );
                put( "time", "服务器当前时间" );
                put( "uptime", "服务器本次启动以来,总共运行时间" );
                put( "connection_structures", "服务器分配的连接结构数" );
                put( "total_connections", "服务器本次启动以来,累计响应连接总次数" );
                put( "curr_connections", "当前打开的连接数" );
                put( "limit_maxbytes", "允许服务支配的最大内存容量" );
                put( "bytes", "当前已使用的内存容量" );
                put( "bytes_written", "服务器本次启动以来,写入的数据量" );
                put( "bytes_read", "服务器本次启动以来,读取的数据量" );
                put( "total_items", "服务器本次启动以来,曾存储的Item总个数" );
                put( "curr_items", "当前存储的Item个数" );
                put( "cmd_get", "服务器本次启动以来,执行Get命令总次数" );
                put( "get_hits", "服务器本次启动以来,Get操作的命中次数" );
                put( "get_misses", "服务器本次启动以来,Get操作的未命中次数" );
                put( "cmd_set", "服务器本次启动以来,执行Set命令总次数" );
            }
        };
    }

      /**  
     * @category 保护型构造方法,不允许实例化!
       */ 
     protected   MemCached() {

    }

      /**  
     * @category 操作类入口:获取唯一实例.
     * 
     *   @return   MemCached对象
       */ 
     public   static   MemCached getInstance() {
          return   memCached;
    }
    
      /**  
     * @category 返回是否已经启用memcached内存服务器
     * 
     *   @return   boolean
       */ 
     public   static   boolean   used(){
          return   enUsed;
    }

      /**  
     * @category 插入新记录.
     * @category 前提:记录的Key在缓存中不存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @return   boolean 操作结果
       */ 
     public   boolean   add(String key, Object value) {
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.add(key, value);
        }
    }

      /**  
     * @category 插入新记录并设置超时日期
     * @category 前提:记录的Key在缓存中不存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDate 超时日期
     *   @return   boolean 操作结果
       */ 
     public   boolean   add(String key, Object value, Date expiryDate) {
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.add(key, value, expiryDate);
        }
    }

      /**  
     * @category 插入新记录并设置超时天数
     * @category 前提:记录的Key在缓存中不存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDays 超时天数
     *   @return   boolean 操作结果
       */ 
     public   boolean  add(String key, Object value,  int   expiryDays){
          if (! enUsed){
              return   false  ;
        }  else  {
            Calendar calendar  =  Calendar.getInstance();
            calendar.setTime(  new   Date());
            calendar.add(Calendar.DATE,expiryDays);   //  增加天数 
             return   memClient.add(key, value, calendar.getTime());
        }
    }
    
      /**  
     * @category 插入新记录或更新已有记录
     * @category 解释:记录的Key在缓存中不存在则插入;否则更新
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @return   boolean 操作结果
       */ 
     public   boolean   set(String key, Object value){
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.set(key, value);
        }
    }

      /**  
     * @category 插入新记录或更新已有记录,并设置超时日期
     * @category 解释:记录的Key在缓存中不存在则插入;否则更新
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDate 超时日期
     *   @return   boolean 操作结果
       */ 
     public   boolean   set(String key, Object value, Date expiryDate){
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.set(key, value, expiryDate);
        }
    }

      /**  
     * @category 插入新记录或更新已有记录,并设置超时天数
     * @category 解释:记录的Key在缓存中不存在则插入;否则更新
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDate 超时天数
     *   @return   boolean 操作结果
       */ 
     public   boolean  set(String key, Object value,  int   expiryDays){
          if (! enUsed){
              return   false  ;
        }  else  {
            Calendar calendar  =  Calendar.getInstance();
            calendar.setTime(  new   Date());
            calendar.add(Calendar.DATE,expiryDays);   //  增加天数 
             return   memClient.set(key, value, calendar.getTime());
        }
    }

      /**  
     * @category 更新已有记录
     * @category 前提:记录的Key在缓存中已经存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @return   boolean 操作结果
       */ 
     public   boolean   replace(String key, Object value) {
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.replace(key, value);
        }
    }

      /**  
     * @category 更新已有记录,并设置超时日期
     * @category 前提:该值在缓存中已经存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDate 超时日期
     *   @return   boolean 操作结果
       */ 
     public   boolean   replace(String key, Object value, Date expiryDate) {
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.replace(key, value, expiryDate);
        }
    }

      /**  
     * @category 更新已有记录,并设置超时天数
     * @category 前提:该值在缓存中已经存在
     *   @param   key 记录的主键
     *   @param   value 记录的内容
     *   @param   expiryDays 超时天数
     *   @return   boolean 操作结果
       */ 
     public   boolean  replace(String key, Object value,  int   expiryDays) {
          if (! enUsed){
              return   false  ;
        }  else  {
            Calendar calendar  =  Calendar.getInstance();
            calendar.setTime(  new   Date());
            calendar.add(Calendar.DATE,expiryDays);   //  增加天数 
             return   memClient.replace(key, value, calendar.getTime());
        }
    }

      /**  
     * @category 返回单条记录
     * 
     *   @param   key 记录的主键
     *   @return   记录的内容
       */ 
     public   Object get(String key) {
          if (! enUsed){
              return   null  ;
        }  else  {
              return   memClient.get(key);
        }
    }

      /**  
     * @category 返回多条记录
     * 
     *   @param   keys 记录的主键数组
     *   @return   Map<String, Object> 多条记录的内容
       */ 
     public  Map<String, Object>  get(String[] keys) {
          if (! enUsed){
              return   null  ;
        }  else  {
              return   memClient.getMulti(keys);
        }
    }
    
      /**  
     * @category 删除记录
     * @category 执行该方法之后,使用stats的统计结果会同步更新
     *   @param   key 记录的主键
     *   @return   操作结果
       */ 
     public   boolean   delete(String key){
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.delete(key);
        }
    }

      /*  
     * ****************************************************************************************************************
     * 下面的6个方法都是为了对memcached服务器进行监控及管理所用的,可能对服务器造成阻塞,所以除Debug以外,不推荐使用!
       */ 
    
     /**  
     * @category 清空全部缓存数据。*慎用!!
     * @category 执行该方法之后,使用stats的统计结果不会马上发生变化,每get一个不存在的item之后,该item的值才会被动清空
     *   @return   操作结果
       */ 
     public   boolean   flushAll(){
          if (! enUsed){
              return   false  ;
        }  else  {
              return   memClient.flushAll();
        }
    }
    
      /**  
     * @category 返回可用的服务器列表
     *   @return   数组(服务器地址:端口)
       */ 
     public   String[] servers(){
          if (!enUsed)  return   null  ;
          return   serverListArr;
    }
    
      /**  
     * @category 返回所有缓存服务器当前的运行状态

     *   @return  
     * 
     *   Map
     *    |-- Key : ServerName01, Value : LinkedHashMap
     *    |                                |-- Key : statName01, Value : statValue
     *    |                                |-- ...
     *    |
     *    |-- Key : ServerName02, Value : LinkedHashMap
     *    |                                |-- Key : statName01, Value : statValue
     *    |                                |-- ...
     *    |
     *    |-- ...
     *  
       */  
     public  Map<String,LinkedHashMap<String, String>>  stats(){
          if (!enUsed)  return   null  ;
        Map <String,LinkedHashMap<String, String>> retMap =  new  HashMap<String,LinkedHashMap<String, String>> ();
          for  (String server : serverListArr){
            LinkedHashMap <String, String> serverStats =  this  .stats(server);
            retMap.put(server, serverStats);
        }
          return   retMap;
    }
    
      /**  
     * @category 返回指定服务器当前的运行状态
     *   @param   server 服务器地址:端口
     * 
     * 优化: 参数名称中文显示
     * 优化: 毫秒数转换为小时
     * 优化: 字节数转换为MB或KB
     * 优化: UNIX时间戳转换为标准时间
     * 优化: 参数显示顺序更加直观
     * 
     *   @return   LinkedHashMap<String, String> 可对Map进行有序遍历
     *  
       */  
     public  LinkedHashMap<String, String>  stats(String server){
          if (!enUsed)  return   null  ;
        LinkedHashMap <String, String> retMap =  new  LinkedHashMap<String, String> ();
        Map <String, Map<String, String>> statsList = memClient.stats( new   String[]{server});
          //  System.out.println(memClient.stats().toString()); 
        DecimalFormat format =  new  DecimalFormat("0.0" );
          for  (Object serverTitle : statsList.keySet().toArray()){
            Map <String, String> serverStats = (Map<String, String> )statsList.get(serverTitle);
            retMap.put(statsItems.get( "pid"), serverStats.get("pid").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "version"), serverStats.get("version").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "pointer_size"), serverStats.get("pointer_size").replaceAll("\\r\\n", "") + "位" );
            retMap.put(statsItems.get( "time"),  new  java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( new  Date(Long.parseLong(serverStats.get("time").replaceAll("\\r\\n", "")) * 1000 )).toString());
            retMap.put(statsItems.get( "uptime"), format.format(Double.parseDouble(serverStats.get("uptime").replaceAll("\\r\\n", ""))/(60*60)) + "小时" );
            retMap.put(statsItems.get( "connection_structures"), serverStats.get("connection_structures").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "total_connections"), serverStats.get("total_connections").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "curr_connections"), serverStats.get("curr_connections").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "limit_maxbytes"), format.format(Double.parseDouble(serverStats.get("limit_maxbytes").replaceAll("\\r\\n", ""))/(1024*1024)) + "MB" );
            retMap.put(statsItems.get( "bytes"), format.format(Double.parseDouble(serverStats.get("bytes").replaceAll("\\r\\n", ""))/(1024*1024)) + "MB" );
            retMap.put(statsItems.get( "bytes_written"), format.format(Double.parseDouble(serverStats.get("bytes_written").replaceAll("\\r\\n", ""))/(1024)) + "KB" );
            retMap.put(statsItems.get( "bytes_read"), format.format(Double.parseDouble(serverStats.get("bytes_read").replaceAll("\\r\\n", ""))/(1024)) + "KB" );
            retMap.put(statsItems.get( "total_items"), serverStats.get("total_items").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "curr_items"), serverStats.get("curr_items").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "cmd_get"), serverStats.get("cmd_get").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "get_hits"), serverStats.get("get_hits").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "get_misses"), serverStats.get("get_misses").replaceAll("\\r\\n", "" ));
            retMap.put(statsItems.get( "cmd_set"), serverStats.get("cmd_set").replaceAll("\\r\\n", "" ));
        }
          return   retMap;
    }
    
      /**  
     * @category 返回指定服务器及Slab中当前使用的item列表
     *   @param   server 服务器地址:端口
     *   @param   slab SlabId
     *   @param   counter 最多显示items条数
     *   @return 
      */ 
     public  LinkedList<String> items(String server,  int  slab,  int   counter){
          if (!enUsed)  return   null  ;
        LinkedList <String> ret =  new  LinkedList<String> ();
        Map <String, String> itemsKey = memClient.statsCacheDump( new   String[]{server}, slab, counter).get(server);
          for  (Object key : itemsKey.keySet().toArray()){
            ret.add(key.toString());
        }
          return   ret;
    }
    
      /**  
     * @category 返回指定服务器当前使用的SlabsID列表
     *   @param   server 服务器地址:端口
     *   @return 
      */ 
     public  LinkedList<Integer>  slabs(String server){
          if (!enUsed)  return   null  ;
        LinkedList <Integer> slabsId =  new  LinkedList<Integer> ();
        Map <String, String> itemsMap = memClient.statsItems( new   String[]{server}).get(server);
        Object[] itemsArr  =  itemsMap.keySet().toArray();
          for ( int  i=0, len=itemsArr.length; i<len; i+=2 ){
            slabsId.add(Integer.parseInt(itemsArr[i].toString().split( ":")[1 ]));
        }
          return   slabsId;
    }

      /*  
     * 上面的6个方法都是为了对memcached服务器进行监控及管理所用的,可能对服务器造成阻塞,所以除Debug以外,不推荐使用!
     * ****************************************************************************************************************
       */ 
    
     /**  
     * 使用示例
       */ 
     public   static   void   main(String[] args) {
        
          //  初始化memcached操作类对象 
        MemCached cache =  MemCached.getInstance();
        
          //  验证memcached服务是否已启用 
         if (! cache.used()){
            System.out.println( "memcached服务未启用!" );
              return  ;
        }
        
          //  插入新记录 
        System.out.println("开始插入新记录(add):\r\n===================================" );
        System.out.println( "keyTest01:" + cache.add("keyTest01", "keyTest01Content" ));
        System.out.println( "keyTest02:" + cache.add("keyTest02", "keyTest02Content" ));
        System.out.println( "插入新记录操作完成\r\n===================================" );
        
          //  读取单条记录 
        System.out.println("读取单条记录(get):\r\n===================================" );
        System.out.println( "keyTest01:" + cache.get("keyTest01" ));
        System.out.println( "keyTest02:" + cache.get("keyTest02" ));
        System.out.println( "读取单条记录操作完成\r\n===================================" );
        
          //  读取多条记录 
        System.out.println("读取多条记录(add):\r\n===================================" );
        System.out.println( "keyTest01、keyTest02:" + cache.get( new  String[]{"keyTest01", "keyTest02" }));
        System.out.println( "读取多条记录操作完成\r\n===================================" );
        
          //  修改记录值 
        System.out.println("修改记录值(replace):\r\n===================================" );
        System.out.println( "keyTest01:" + cache.get("keyTest01" ));
        System.out.println( "keyTest01:" + cache.replace("keyTest01", "keyTest01ContentReplace!" ));
        System.out.println( "keyTest01:" + cache.get("keyTest01" ));
        System.out.println( "修改记录值操作完成\r\n===================================" );
        
          //  添加或修改记录 
        System.out.println("添加或修改记录(set):\r\n===================================" );
        System.out.println( "keyTest03:" + cache.set("keyTest03", "keyTest03Content" ));
        System.out.println( "keyTest03:" + cache.get("keyTest03" ));
        System.out.println( "keyTest03:" + cache.set("keyTest03", "keyTest03ContentReplace!" ));
        System.out.println( "keyTest03:" + cache.get("keyTest03" ));
        System.out.println( "添加或修改记录操作完成\r\n===================================" );
        
          //  删除记录 
        System.out.println("删除记录(delete):\r\n===================================" );
        System.out.println( "keyTest01:" + cache.delete("keyTest01" ));
        System.out.println( "keyTest02:" + cache.delete("keyTest02" ));
        System.out.println( "keyTest03:" + cache.get("keyTest03" ));
        System.out.println( "keyTest03:" + cache.delete("keyTest03" ));
        System.out.println( "keyTest03:" + cache.get("keyTest03" ));
        System.out.println( "修改记录值操作完成\r\n===================================" );
        
          //  打印当前的服务器参数及统计信息 
        System.out.println("服务器参数及统计信息(stats):\r\n===================================" );
        Map statsList  =  cache.stats();
          for  (Object server : statsList.keySet().toArray()){
            System.out.println( "-------------------------\r\n服务器:" + server + " : \r\n-------------------------" );
            LinkedHashMap serverStats  =  (LinkedHashMap)statsList.get(server);
              for  (Object statKey : serverStats.keySet().toArray()){
                System.out.println(statKey  + " : " +  serverStats.get(statKey));
            }
        }
    }
}  

五、OVER!

 

---------------------------------------------------------------------------

一天一天过去了,第三天我想通了 ... ...  

 

 

 

分类:  常用工具箱 ,  服务器相关 ,  数据库

标签:  java ,  封装 ,  memcached ,  操作类 ,  连接池 ,  服务器检测 ,  遍历item

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于memcached客户端操作类的详细内容...

  阅读:35次