1.memcached client for java客户端API:memcached client for java
网址:http://www.whalin.com/memcached
最新版本:java_memcached-release_2.0.1
操作示例:
- import com.danga.MemCached.*;
- import org.apache.log4j.*;
- public class TestMemcached {
- public static void main(String[] args) {
- /*初始化SockIOPool,管理memcached的连接池*/
- String[] servers = { "192.168.1.20:12111" };
- SockIOPool pool = SockIOPool.getInstance();
- pool.setServers(servers);
- pool.setFailover(true);
- pool.setInitConn(10);
- pool.setMinConn(5);
- pool.setMaxConn(250);
- pool.setMaintSleep(30);
- pool.setNagle(false);
- pool.setSocketTO(3000);
- pool.setAliveCheck(true);
- pool.initialize();
- /*建立MemcachedClient实例*/
- MemCachedClient memCachedClient = new MemCachedClient();
- for (int i = 0; i < 10; i++) {
- /*将对象加入到memcached缓存*/
- boolean success = memCachedClient.set("" + i, "Hello!");
- /*从memcached缓存中按key值取对象*/
- String result = (String) memCachedClient.get("" + i);
- System.out.println(String.format("set( %d ): %s", i, success));
- System.out.println(String.format("get( %d ): %s", i, result));
- }
- }
- }
2.spymemcached 客户端API:spymemcached client
网址:http://code.google.com/p/spymemcached/
最新版本:memcached-2.1.jar
操作示例:
用spymemcached将对象存入缓存
- import java.net.InetSocketAddress;
- import java.util.concurrent.Future;
- import net.spy.memcached.MemcachedClient;
- public class MClient {
- public static void main(String[] args){
- try{
- /*建立MemcachedClient 实例,并指定memcached服务的IP地址和端口号*/
- MemcachedClient mc = new MemcachedClient(new InetSocketAddress("192.168.1.20", 12111));
- Future<Boolean> b = null;
- /*将key值,过期时间(秒)和要缓存的对象set到memcached中*/
- b = mc.set("neea:testDaF:ksIdno", 900, "someObject");
- if(b.get().booleanValue()==true){
- mc.shutdown();
- }
- }
- catch(Exception ex){
- ex.printStackTrace();
- }
- }
- }
用spymemcached从缓存中取得对象
- import java.net.InetSocketAddress;
- import java.util.concurrent.Future;
- import net.spy.memcached.MemcachedClient;
- public class MClient {
- public static void main(String[] args){
- try{
- /*建立MemcachedClient 实例,并指定memcached服务的IP地址和端口号*/
- MemcachedClient mc = new MemcachedClient(new InetSocketAddress("192.168.1.20", 12111));
- /*按照key值从memcached中查找缓存,不存在则返回null */
- Object b = mc.get("neea:testDaF:ksIdno ");
- mc.shutdown();
- }
- catch(Exception ex){
- ex.printStackTrace();
- }
- }
- }
3.两种API比较
memcached client for java:较早推出的memcached JAVA客户端API,应用广泛,运行比较稳定。
spymemcached:A simple, asynchronous, single-threaded memcached client written in java. 支持异步,单线程的memcached客户端,用到了java1.5版本的concurrent和nio,存取速度会高于前者,但是稳定性不好,测试中常报timeOut等相关异常。
由于memcached client for java发布了新版本,性能上有所提高,并且运行稳定,所以建议使用memcached client for java。
本文将对在Java环境下Memcached应用进行详细介绍。Memcached主要是集群环境下的缓存解决方案,可以运行在Java或者.NET平台上,这里我们主要讲的是Windows下的Memcached应用。
这些天在设计SNA的架构,接触了一些远程缓存、集群、session复制等的东西,以前做企业应用的时候感觉作用不大,现在设计面对internet的系统架构时就非常有用了,而且在调试后看到压力测试的情况还是比较好的。
在缓存的选择上有过很多的思考,虽然说memcached结合java在序列化上性能不怎么样,不过也没有更好的集群环境下的缓存解决方案了,就选择了memcached。本来计划等公司买的服务器到位装个linux再来研究memcached,但这两天在找到了一个windows下的Memcached版本,就动手开始调整现有的框架了。
Windows下的Server端很简单,不用安装,双击运行后默认服务端口是11211,没有试着去更改端口,因为反正以后会用Unix版本,到时再记录安装步骤。下载客户端的JavaAPI包,接口非常简单,参考API手册上就有现成的例子。
目标,对旧框架缓存部分进行改造:
1、缓存工具类
2、hibernate的provider
3、用缓存实现session机制
今天先研究研究缓存工具类的改造,在旧框架中部分函数用了ehcache对执行结果进行了缓存处理,现在目标是提供一个缓存工具类,在配置文件中配置使用哪种缓存(memcached或ehcached),使其它程序对具体的缓存不依赖,同时使用AOP方式来对方法执行结果进行缓存。
首先是工具类的实现:
在Spring中配置
Java代码
- <bean id="cacheManager"
- class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation">
- <value>classpath:ehcache.xmlvalue
- property
- bean
- <bean id="localCache"
- class="org.springframework.cache.ehcache.EhCacheFactoryBean">
- <property name="cacheManager" ref="cacheManager" />
- <property name="cacheName"
- value="×××.cache.LOCAL_CACHE" />
- bean
- <bean id="cacheService"
- class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">
- <property name="cacheServerList" value="${cache.servers}"/>
- <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>
- <property name="cacheCluster" value="${cache.cluster}"/>
- <property name="localCache" ref="localCache"/>
- bean
- <bean id="cacheManager"
- class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation">
- <value>classpath:ehcache.xmlvalue
- property
- bean
- <bean id="localCache"
- class="org.springframework.cache.ehcache.EhCacheFactoryBean">
- <property name="cacheManager" ref="cacheManager" />
- <property name="cacheName"
- value="×××.cache.LOCAL_CACHE" />
- bean
- <bean id="cacheService"
- class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">
- <property name="cacheServerList" value="${cache.servers}"/>
- <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>
- <property name="cacheCluster" value="${cache.cluster}"/>
- <property name="localCache" ref="localCache"/>
- bean
在properties文件中配置${cache.servers} ${cache.cacheServerWeights} ${cache.cluster}
具体工具类的代码
Java代码
- /**
- * @author Marc
- *
- */
- public class CacheService {
- private Log logger = LogFactory.getLog(getClass());
- private Cache localCache;
- String cacheServerList;
- String cacheServerWeights;
- boolean cacheCluster = false;
- int initialConnections = 10;
- int minSpareConnections = 5;
- int maxSpareConnections = 50;
- long maxIdleTime = 1000 * 60 * 30; // 30 minutes
- long maxBusyTime = 1000 * 60 * 5; // 5 minutes
- long maintThreadSleep = 1000 * 5; // 5 seconds
- int socketTimeOut = 1000 * 3; // 3 seconds to block on reads
- int socketConnectTO = 1000 * 3; // 3 seconds to block on initial
- // connections. If 0, then will use blocking
- // connect (default)
- boolean failover = false; // turn off auto-failover in event of server
- // down
- boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in
- // pool
- MemCachedClient mc;
- public CacheService(){
- mc = new MemCachedClient();
- mc.setCompressEnable(false);
- }
- /**
- * 放入
- *
- */
- public void put(String key, Object obj) {
- Assert.hasText(key);
- Assert.notNull(obj);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- mc.set(key, obj);
- } else {
- Element element = new Element(key, (Serializable) obj);
- localCache.put(element);
- }
- }
- /**
- * 删除
- */
- public void remove(String key){
- Assert.hasText(key);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- mc.delete(key);
- }else{
- localCache.remove(key);
- }
- }
- /**
- * 得到
- */
- public Object get(String key) {
- Assert.hasText(key);
- Assert.notNull(localCache);
- Object rt = null;
- if (this.cacheCluster) {
- rt = mc.get(key);
- } else {
- Element element = null;
- try {
- element = localCache.get(key);
- } catch (CacheException cacheException) {
- throw new DataRetrievalFailureException("Cache failure: "
- + cacheException.getMessage());
- }
- if(element != null)
- rt = element.getValue();
- }
- return rt;
- }
- /**
- * 判断是否存在
- *
- */
- public boolean exist(String key){
- Assert.hasText(key);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- return mc.keyExists(key);
- }else{
- return this.localCache.isKeyInCache(key);
- }
- }
- private void init() {
- if (this.cacheCluster) {
- String[] serverlist = cacheServerList.split(",");
- Integer[] weights = this.split(cacheServerWeights);
- // initialize the pool for memcache servers
- SockIOPool pool = SockIOPool.getInstance();
- pool.setServers(serverlist);
- pool.setWeights(weights);
- pool.setInitConn(initialConnections);
- pool.setMinConn(minSpareConnections);
- pool.setMaxConn(maxSpareConnections);
- pool.setMaxIdle(maxIdleTime);
- pool.setMaxBusyTime(maxBusyTime);
- pool.setMaintSleep(maintThreadSleep);
- pool.setSocketTO(socketTimeOut);
- pool.setSocketConnectTO(socketConnectTO);
- pool.setNagle(nagleAlg);
- pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
- pool.initialize();
- logger.info("初始化memcached pool!");
- }
- }
- private void destory() {
- if (this.cacheCluster) {
- SockIOPool.getInstance().shutDown();
- }
- }
- }
- /**
- * @author Marc
- *
- */
- public class CacheService {
- private Log logger = LogFactory.getLog(getClass());
- private Cache localCache;
- String cacheServerList;
- String cacheServerWeights;
- boolean cacheCluster = false;
- int initialConnections = 10;
- int minSpareConnections = 5;
- int maxSpareConnections = 50;
- long maxIdleTime = 1000 * 60 * 30; // 30 minutes
- long maxBusyTime = 1000 * 60 * 5; // 5 minutes
- long maintThreadSleep = 1000 * 5; // 5 seconds
- int socketTimeOut = 1000 * 3; // 3 seconds to block on reads
- int socketConnectTO = 1000 * 3; // 3 seconds to block on initial
- // connections. If 0, then will use blocking
- // connect (default)
- boolean failover = false; // turn off auto-failover in event of server
- // down
- boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in
- // pool
- MemCachedClient mc;
- public CacheService(){
- mc = new MemCachedClient();
- mc.setCompressEnable(false);
- }
- /**
- * 放入
- *
- */
- public void put(String key, Object obj) {
- Assert.hasText(key);
- Assert.notNull(obj);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- mc.set(key, obj);
- } else {
- Element element = new Element(key, (Serializable) obj);
- localCache.put(element);
- }
- }
- /**
- * 删除
- */
- public void remove(String key){
- Assert.hasText(key);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- mc.delete(key);
- }else{
- localCache.remove(key);
- }
- }
- /**
- * 得到
- */
- public Object get(String key) {
- Assert.hasText(key);
- Assert.notNull(localCache);
- Object rt = null;
- if (this.cacheCluster) {
- rt = mc.get(key);
- } else {
- Element element = null;
- try {
- element = localCache.get(key);
- } catch (CacheException cacheException) {
- throw new DataRetrievalFailureException("Cache failure: "
- + cacheException.getMessage());
- }
- if(element != null)
- rt = element.getValue();
- }
- return rt;
- }
- /**
- * 判断是否存在
- *
- */
- public boolean exist(String key){
- Assert.hasText(key);
- Assert.notNull(localCache);
- if (this.cacheCluster) {
- return mc.keyExists(key);
- }else{
- return this.localCache.isKeyInCache(key);
- }
- }
- private void init() {
- if (this.cacheCluster) {
- String[] serverlist = cacheServerList.split(",");
- Integer[] weights = this.split(cacheServerWeights);
- // initialize the pool for memcache servers
- SockIOPool pool = SockIOPool.getInstance();
- pool.setServers(serverlist);
- pool.setWeights(weights);
- pool.setInitConn(initialConnections);
- pool.setMinConn(minSpareConnections);
- pool.setMaxConn(maxSpareConnections);
- pool.setMaxIdle(maxIdleTime);
- pool.setMaxBusyTime(maxBusyTime);
- pool.setMaintSleep(maintThreadSleep);
- pool.setSocketTO(socketTimeOut);
- pool.setSocketConnectTO(socketConnectTO);
- pool.setNagle(nagleAlg);
- pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);
- pool.initialize();
- logger.info("初始化memcachedpool!");
- }
- }
- private void destory() {
- if (this.cacheCluster) {
- SockIOPool.getInstance().shutDown();
- }
- }
- }
然后实现函数的AOP拦截类,用来在函数执行前返回缓存内容
Java代码
- public class CachingInterceptor implements MethodInterceptor {
- private CacheService cacheService;
- private String cacheKey;
- public void setCacheKey(String cacheKey) {
- this.cacheKey = cacheKey;
- }
- public void setCacheService(CacheService cacheService) {
- this.cacheService = cacheService;
- }
- public Object invoke(MethodInvocation invocation) throws Throwable {
- Object result = cacheService.get(cacheKey);
- //如果函数返回结果不在Cache中,执行函数并将结果放入Cache
- if (result == null) {
- result = invocation.proceed();
- cacheService.put(cacheKey,result);
- }
- return result;
- }
- }
- public class CachingInterceptor implements MethodInterceptor {
- private CacheService cacheService;
- private String cacheKey;
- public void setCacheKey(String cacheKey) {
- this.cacheKey = cacheKey;
- }
- public void setCacheService(CacheService cacheService) {
- this.cacheService = cacheService;
- }
- public Object invoke(MethodInvocation invocation) throws Throwable {
- Object result = cacheService.get(cacheKey);
- //如果函数返回结果不在Cache中,执行函数并将结果放入Cache
- if (result == null) {
- result = invocation.proceed();
- cacheService.put(cacheKey,result);
- }
- return result;
- }
- }
Spring的AOP配置如下:
Java代码
- <aop:config proxy-target-class="true">
- <aop:advisor
- pointcut="execution(* ×××.PoiService.getOne(..))"
- advice-ref="PoiServiceCachingAdvice" />
- aop:config
- <bean id="BasPoiServiceCachingAdvice"
- class="×××.core.cache.CachingInterceptor">
- <property name="cacheKey" value="PoiService" />
- <property name="cacheService" ref="cacheService" />
- bean