java memcached 封装_原创:分享封装好的面向JAVA的memcached客户端操作类

packagecom.common;importjava.io.File;importjava.text.DecimalFormat;importjava.util.ArrayList;importjava.util.Calendar;importjava.util.LinkedList;importjava.util.List;importjava.util.Date;importjava.util.HashMap;importjava.util.LinkedHashMap;importjava.util.Map;importorg.apache.commons.net.telnet.TelnetClient;importorg.dom4j.Document;importorg.dom4j.Element;importorg.dom4j.Node;importorg.dom4j.io.SAXReader;importcom.danga.MemCached.MemCachedClient;importcom.danga.MemCached.SockIOPool;/*** @category memcached内存数据库操作类

*@author网无忌(netwild)

* @email inetwild@gmail.com

* @qq 52100641

*@version1.0*/

public classMemCached {//是否启用MemCached内存数据库

protected static boolean enUsed = true;//创建全局唯一的可实例化对象

protected static MemCached memCached = newMemCached();//初始化MemCached客户端对象

protected static MemCachedClient memClient = newMemCachedClient();//定义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 MapserverConfig;//定义MemCached服务器运行状态表,用于保存各状态的中文解释

protected static HashMapstatsItems;//设置全局静态参数,以下代码在整个服务器运行周期内仅运行一次!

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 voidinitConfig(){//初始化可用的MemCached服务器列表默认值(本机)

serverListArr[0] = "127.0.0.1:11211";

weightListArr[0] = 1;//初始化MemCached服务器运行环境表(默认值),当某参数未在配置文件中进行定义时,将使用该默认值

serverConfig = new HashMap(){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 = newSAXReader();

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 serverDoms = Servers.elements(); //备用的服务器列表

List serverUsed = new ArrayList(); //经检测,实际可用的服务器列表

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(){

{

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 保护型构造方法,不允许实例化!*/

protectedMemCached() {

}/*** @category 操作类入口:获取唯一实例.

*

*@returnMemCached对象*/

public staticMemCached getInstance() {returnmemCached;

}/*** @category 返回是否已经启用memcached内存服务器

*

*@returnboolean*/

public static booleanused(){returnenUsed;

}/*** @category 插入新记录.

* @category 前提:记录的Key在缓存中不存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@returnboolean 操作结果*/

public booleanadd(String key, Object value) {if(!enUsed){return false;

}else{returnmemClient.add(key, value);

}

}/*** @category 插入新记录并设置超时日期

* @category 前提:记录的Key在缓存中不存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDate 超时日期

*@returnboolean 操作结果*/

public booleanadd(String key, Object value, Date expiryDate) {if(!enUsed){return false;

}else{returnmemClient.add(key, value, expiryDate);

}

}/*** @category 插入新记录并设置超时天数

* @category 前提:记录的Key在缓存中不存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDays 超时天数

*@returnboolean 操作结果*/

public boolean add(String key, Object value, intexpiryDays){if(!enUsed){return false;

}else{

Calendar calendar=Calendar.getInstance();

calendar.setTime(newDate());

calendar.add(Calendar.DATE,expiryDays);//增加天数

returnmemClient.add(key, value, calendar.getTime());

}

}/*** @category 插入新记录或更新已有记录

* @category 解释:记录的Key在缓存中不存在则插入;否则更新

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@returnboolean 操作结果*/

public booleanset(String key, Object value){if(!enUsed){return false;

}else{returnmemClient.set(key, value);

}

}/*** @category 插入新记录或更新已有记录,并设置超时日期

* @category 解释:记录的Key在缓存中不存在则插入;否则更新

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDate 超时日期

*@returnboolean 操作结果*/

public booleanset(String key, Object value, Date expiryDate){if(!enUsed){return false;

}else{returnmemClient.set(key, value, expiryDate);

}

}/*** @category 插入新记录或更新已有记录,并设置超时天数

* @category 解释:记录的Key在缓存中不存在则插入;否则更新

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDate 超时天数

*@returnboolean 操作结果*/

public boolean set(String key, Object value, intexpiryDays){if(!enUsed){return false;

}else{

Calendar calendar=Calendar.getInstance();

calendar.setTime(newDate());

calendar.add(Calendar.DATE,expiryDays);//增加天数

returnmemClient.set(key, value, calendar.getTime());

}

}/*** @category 更新已有记录

* @category 前提:记录的Key在缓存中已经存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@returnboolean 操作结果*/

public booleanreplace(String key, Object value) {if(!enUsed){return false;

}else{returnmemClient.replace(key, value);

}

}/*** @category 更新已有记录,并设置超时日期

* @category 前提:该值在缓存中已经存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDate 超时日期

*@returnboolean 操作结果*/

public booleanreplace(String key, Object value, Date expiryDate) {if(!enUsed){return false;

}else{returnmemClient.replace(key, value, expiryDate);

}

}/*** @category 更新已有记录,并设置超时天数

* @category 前提:该值在缓存中已经存在

*@paramkey 记录的主键

*@paramvalue 记录的内容

*@paramexpiryDays 超时天数

*@returnboolean 操作结果*/

public boolean replace(String key, Object value, intexpiryDays) {if(!enUsed){return false;

}else{

Calendar calendar=Calendar.getInstance();

calendar.setTime(newDate());

calendar.add(Calendar.DATE,expiryDays);//增加天数

returnmemClient.replace(key, value, calendar.getTime());

}

}/*** @category 返回单条记录

*

*@paramkey 记录的主键

*@return记录的内容*/

publicObject get(String key) {if(!enUsed){return null;

}else{returnmemClient.get(key);

}

}/*** @category 返回多条记录

*

*@paramkeys 记录的主键数组

*@returnMap 多条记录的内容*/

public Mapget(String[] keys) {if(!enUsed){return null;

}else{returnmemClient.getMulti(keys);

}

}/*** @category 删除记录

* @category 执行该方法之后,使用stats的统计结果会同步更新

*@paramkey 记录的主键

*@return操作结果*/

public booleandelete(String key){if(!enUsed){return false;

}else{returnmemClient.delete(key);

}

}/** ****************************************************************************************************************

* 下面的6个方法都是为了对memcached服务器进行监控及管理所用的,可能对服务器造成阻塞,所以除Debug以外,不推荐使用!*/

/*** @category 清空全部缓存数据。*慎用!!

* @category 执行该方法之后,使用stats的统计结果不会马上发生变化,每get一个不存在的item之后,该item的值才会被动清空

*@return操作结果*/

public booleanflushAll(){if(!enUsed){return false;

}else{returnmemClient.flushAll();

}

}/*** @category 返回可用的服务器列表

*@return数组(服务器地址:端口)*/

publicString[] servers(){if(!enUsed) return null;returnserverListArr;

}/*** @category 返回所有缓存服务器当前的运行状态

*@return*

* Map

* |-- Key : ServerName01, Value : LinkedHashMap

* | |-- Key : statName01, Value : statValue

* | |-- ...

* |

* |-- Key : ServerName02, Value : LinkedHashMap

* | |-- Key : statName01, Value : statValue

* | |-- ...

* |

* |-- ...

**/

public Map>stats(){if(!enUsed) return null;

Map> retMap = new HashMap>();for(String server : serverListArr){

LinkedHashMap serverStats = this.stats(server);

retMap.put(server, serverStats);

}returnretMap;

}/*** @category 返回指定服务器当前的运行状态

*@paramserver 服务器地址:端口

*

* 优化: 参数名称中文显示

* 优化: 毫秒数转换为小时

* 优化: 字节数转换为MB或KB

* 优化: UNIX时间戳转换为标准时间

* 优化: 参数显示顺序更加直观

*

*@returnLinkedHashMap 可对Map进行有序遍历

**/

public LinkedHashMapstats(String server){if(!enUsed) return null;

LinkedHashMap retMap = new LinkedHashMap();

Map> statsList = memClient.stats(newString[]{server});//System.out.println(memClient.stats().toString());

DecimalFormat format = new DecimalFormat("0.0");for(Object serverTitle : statsList.keySet().toArray()){

Map serverStats = (Map)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", ""));

}returnretMap;

}/*** @category 返回指定服务器及Slab中当前使用的item列表

*@paramserver 服务器地址:端口

*@paramslab SlabId

*@paramcounter 最多显示items条数

*@return

*/

public LinkedList items(String server, int slab, intcounter){if(!enUsed) return null;

LinkedList ret = new LinkedList();

Map itemsKey = memClient.statsCacheDump(newString[]{server}, slab, counter).get(server);for(Object key : itemsKey.keySet().toArray()){

ret.add(key.toString());

}returnret;

}/*** @category 返回指定服务器当前使用的SlabsID列表

*@paramserver 服务器地址:端口

*@return

*/

public LinkedListslabs(String server){if(!enUsed) return null;

LinkedList slabsId = new LinkedList();

Map itemsMap = memClient.statsItems(newString[]{server}).get(server);

Object[] itemsArr=itemsMap.keySet().toArray();for(int i=0, len=itemsArr.length; i

slabsId.add(Integer.parseInt(itemsArr[i].toString().split(":")[1]));

}returnslabsId;

}/** 上面的6个方法都是为了对memcached服务器进行监控及管理所用的,可能对服务器造成阻塞,所以除Debug以外,不推荐使用!

* *****************************************************************************************************************/

/*** 使用示例*/

public static voidmain(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));

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值