memcache实现公共计数器网站
在反问题的过程中遇到的最近项目。网上查了很多资料并没有完全实现。
因此,要找到适合自己的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
版权声明:本文博主原创文章。博客,未经同意不得转载。
memcache实现公共计数器网站的更多相关文章
- 最全免费CDN公共库——网站提速
开源静态文件 CDN 我们的目标是提供这样一个仓库,让它尽可能全面收录优秀的开源库,并免费为之提供 CDN 加速服务,使之有更好的访问速度和稳定的环境.同时,我们也提供开源库源接入的入口,让所有人都可 ...
- 免费CDN公共库——网站提速 静态资源库
原文链接:https://blog.geekzhao.me/cdnjs.html 新浪SAE公共资源 推荐指数★★★ 支持https http://lib.sinaapp.com/js/jquery/ ...
- memcache的windows下的安装和简单使用
原文:memcache的windows下的安装和简单使用 memcache是为了解决网站访问量大,数据库压力倍增的解决方案之一,由于其简单实用,很多站点现在都在使用memcache,但是memcach ...
- RDBMS,memcache
1.RDBMS即关系数据库管理系统(Relational Database Management System),是将数据组织为相关的行和列的系统,而管理关系数据库的计算机软件就是关系数据库管理系统, ...
- memcache缓存雪崩、缓存无底洞、缓存穿透、永久数据被踢现象
一.缓存雪崩现象 缓存雪崩一般是由某个缓存节点失效,导致其他节点的缓存命中率下降, 缓存中缺失的数据去数据库查询,短时间内造成数据库服务器崩溃, 重启DB短期又被压跨,但新数据的缓存也更新一些,DB反 ...
- hihocoder1069 最近公共祖先·三(tarjin算法)(并查集)
#1069 : 最近公共祖先·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的“最近公共祖先”网站,但是 ...
- 最近公共祖先-三(RMQ-ST)
描述 上上回说到,小Hi和小Ho使用了Tarjan算法来优化了他们的"最近公共祖先"网站,但是很快这样一个离线算法就出现了问题:如果只有一个人提出了询问,那么小Hi和小Ho很难决定 ...
- Jmeter系列(34)- 详解 Counter 计数器
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 简单介绍 计数器的作用:循环递增生成数 ...
- 最常见的 20 个 jQuery 面试问题及答案
jQuery 面试问题和答案 JavaScript 是客户端脚本的标准语言,而 jQuery 使得编写 JavaScript 更加简单.你可以只用写几行的jQuery 代码就能实现更多的东西. 它是最 ...
随机推荐
- C# ToString常用技巧总结
ToString是在开发中最常用的操作,其作用是将其它类型以字符串类型表示.例如: int i=2;i.ToString() //”2″Object o = new Object();o.ToStri ...
- MOS管(场效应管)导通条件
场效应管的导通与截止由栅源电压来控制,对于增强型场效应管来说,N沟道的管子加正向电压即导通,P沟道的管子则加反向电压.一般2V-4V就可以了. 但是,场效应管分为增强型(常开型)和耗尽型(常闭型 ...
- PHP通过链接获取二进制数据的方法
function urltoblob($url){ $data = @file_get_contents($url); //如果file得不到数据,则给空值 if(!$data){ $data = & ...
- DevExpress::XtraBars::BarEditItem获取EditValue值事件
//视图设计器中拖动一个barManager,添加一个bar,再添加一个BarEditItem控件,如下代码: private: DevExpress::XtraEditors::Repository ...
- NodeJs开发学习目录
1.Nodejs基本概念及Nodejs.npm安装测试[2014-06-06] 2.开发工具简介(主要介绍Sublime Text使用) [2014-06-06] 3.Sublime text插件安装 ...
- emmet插件的导入与实用
http://jingyan.baidu.com/article/ff4116259b057c12e48237b8.html http://www.iteye.com/news/27580 分享htm ...
- 2、MyBatis.NET学习笔记之CodeSmith使用
说明:本系列随笔会与CSDN同步发布,当然这里先发,因为这里可以用WLW.但刚才由于误操作,没有重新发上来.只好先在CSDN先发了.重往这里发时图片无法处理,索性直接粘过来吧! 使用框架后一些相关的配 ...
- JAVA线程示范之一种
线程有两种方法生成,这是其中的一种.. MyRunnable.java public class MyRunnable implements Runnable { public void run() ...
- ARM Cortex M3系列GPIO口介绍(工作方式探讨)
一.Cortex M3的GPIO口特性 在介绍GPIO口功能前,有必要先说明一下M3的结构框图,这样能够更好理解总线结构和GPIO所处的位置. Cortex M3结构框图 从图中可以看出 ...
- .net线程入门1-进程
什么是进程 当用户启动了一个程序,这个程序会加载内存和一大堆的资源,这些内存和资源在物理上的分区就是一个进程.一个应用程序也许不仅仅包含一个进程,了解程序和进程不是同一回事是非常重要的. 你可以通过任 ...