最近项目中碰到了一个计数器的实现问题,网上查了很多资料也没有一个完整的实现。所以自己查找xmemcache client和memcache相关的API和说明,找到了一个比较完美的实现方法。
关键类:net.rubyeye.xmemcached.Counter
相关API
实现思路:
获取:
获取的时候默认从memcache中获取,初次获取没获得的话加载数据库获取值,并初始化计数器的值。
更新
先从memcache中获取计数器的值,没有获取到得的话加载数据库获取值,并初始化计数器的值。
然后将计数器加1,获取操作后的返回值,如果是100的整数倍就更新到数据库
以下是关键实现类的代码
package com.liu.memcache.tools;
import java.io.IOException;
import net.rubyeye.xmemcached.Counter;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
import net.rubyeye.xmemcached.utils.AddrUtil;
public class MemCachedTools {
private static final MemCachedTools instance = new MemCachedTools();
/**
* instance
*
* @return
*/
public static MemCachedTools getInstance() {
return instance;
}
private static String memcached_address = ConfigUtil.getInstance()
.getString("memcached_address");
private static String memcached_head=ConfigUtil.getInstance()
.getString("memcached_head");
/**
* 值增加1
* @param key
* @return
*/
public long increaseValue(String key){
long addResult=0;
String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
try {
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses(memcached_address));
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
MemcachedClient memcachedClient = builder.build();
Counter counter=memcachedClient.getCounter(memKey);
addResult=counter.incrementAndGet();
try {
// close memcached client
memcachedClient.shutdown();
} catch (IOException e) {
System.err.println("Shutdown MemcachedClient fail");
e.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
// return ERROR;
}
System.out.println("================"+addResult);
return addResult;
}
/**
* 初始化计数器
* @param key
* @param defaultValue
*/
public void initCounter(String key,long defaultValue){
String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
try {
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses(memcached_address));
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
MemcachedClient memcachedClient = builder.build();
Counter counter=memcachedClient.getCounter(memKey,defaultValue);
counter.set(defaultValue);
try {
// close memcached client
memcachedClient.shutdown();
} catch (IOException e) {
System.err.println("Shutdown MemcachedClient fail");
e.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
// return ERROR;
}
}
/**
* 获取计数器的值
* @param key
* @return
*/
public long getCounterValue(String key){
String memKey=memcached_head+":"+Md5Hex.getDigestMD5(key);
long ret=0;
try {
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
AddrUtil.getAddresses(memcached_address));
builder.setSessionLocator(new KetamaMemcachedSessionLocator());
MemcachedClient memcachedClient = builder.build();
Counter counter=memcachedClient.getCounter(memKey);
ret= counter.get();
try {
// close memcached client
memcachedClient.shutdown();
} catch (IOException e) {
System.err.println("Shutdown MemcachedClient fail");
e.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
// return ERROR;
}
return ret;
}
}
操作计数器实现类
package com.liu.counter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.liu.memcache.tools.MemCachedTools;
/**
* @author chao.liu
* @date 2015-03-06
*
*/
public class CounterService {
protected Log log = LogFactory.getLog(getClass());
public long getStatisticsData() {
String memKey = "count";
Long count = null;
try {
count = (Long) MemCachedTools.getInstance().getCounterValue(memKey);
} catch (Exception e) {
}
if (count == 0) {
try {
// TODO:从数据库加载,此处省略
count = 120L;
} catch (Exception e) {
}
MemCachedTools.getInstance().initCounter(memKey, count);
} else {
// TODO:输出到前台的处理
log.info("StatisticsService.getStatisticsData get data to memcached ...............");
}
return count;
}
/**
* 更新统计数据
*
* @param channelID
* @param moduleID
* @return
*/
public String updateStatisticsData() {
String memKey = "count";
String res = "1";
Long count = null;
try {
count = (Long) MemCachedTools.getInstance().getCounterValue(memKey);
} catch (Exception e) {
}
if (count == 0) {// 空的时候从数据库加载
// TODO:从数据库加载,此处省略
count = 120L;
MemCachedTools.getInstance().initCounter(memKey, count);
}
long addRes = MemCachedTools.getInstance().increaseValue(memKey);
try {
if (addRes != 0) {
if (addRes % 100 == 0) {
// 每100条更新到数据库一次
// update to DB operation
}
}
} catch (Exception e) {
res = "0";
}
return res;
}
public static void main(String[] args) {
CounterService ss=new CounterService();
System.out.println("当前计数条数是:"+ss.getStatisticsData());
ss.updateStatisticsData();
System.out.println("加1后计数条数是:"+ss.getStatisticsData());
}
}
运行效果:
当前计数条数是:123
================124
加1后计数条数是:124
原文地址:http://blog.csdn.net/shanhuhau/article/details/44343159