zoukankan      html  css  js  c++  java
  • 原创:分享封装好的面向JAVA的memcached客户端操作类

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

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

    一、初衷

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

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

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

    二、依赖

    1. memcached-1.2.1-win32memcached.exe) 最主要的
    2. com.danga.MemCachedjava_memcached-release_2.6.6.jar)  最关键的,面向JAVA的memcached客户端lib
    3. org.dom4jdom4j-1.6.1.jar)  用于加载并解析配置文件(xml格式)
    4. org.apache.commons.net.telnetcommons-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!

  • 相关阅读:
    例程详解
    js对数组中有相似属性对象进行合并
    javaScript放大镜特效
    css改变图标颜色
    js自定义日历
    vuecli4.0配置公共scss样式文件
    iframe根据子页面的内容来设置高度
    iframe父子页面交互
    artTemplate模板自定义函数
    javascript数组的增删改和查询
  • 原文地址:https://www.cnblogs.com/netWild/p/memcached.html
Copyright © 2011-2022 走看看