Java环境下的Memcached

1.memcached client for java客户端API:memcached client for java 
网址:http://www.whalin.com/memcached 
最新版本:java_memcached-release_2.0.1 

操作示例: 

Java代码   收藏代码
  1. import com.danga.MemCached.*;  
  2. import org.apache.log4j.*;  
  3. public class TestMemcached {  
  4.     public static void main(String[] args) {  
  5.         /*初始化SockIOPool,管理memcached的连接池*/  
  6.         String[] servers = { "192.168.1.20:12111" };  
  7.         SockIOPool pool = SockIOPool.getInstance();  
  8.         pool.setServers(servers);  
  9.         pool.setFailover(true);  
  10.         pool.setInitConn(10);  
  11.         pool.setMinConn(5);  
  12.         pool.setMaxConn(250);  
  13.         pool.setMaintSleep(30);  
  14.         pool.setNagle(false);  
  15.         pool.setSocketTO(3000);  
  16.         pool.setAliveCheck(true);  
  17.         pool.initialize();  
  18.         /*建立MemcachedClient实例*/  
  19.         MemCachedClient memCachedClient = new MemCachedClient();  
  20.         for (int i = 0; i < 10; i++) {  
  21.             /*将对象加入到memcached缓存*/  
  22.             boolean success = memCachedClient.set("" + i, "Hello!");  
  23.             /*从memcached缓存中按key值取对象*/  
  24.             String result = (String) memCachedClient.get("" + i);  
  25.             System.out.println(String.format("set( %d ): %s", i, success));  
  26.             System.out.println(String.format("get( %d ): %s", i, result));  
  27.         }  
  28.     }  
  29. }  


2.spymemcached 客户端API:spymemcached client 
网址:http://code.google.com/p/spymemcached/ 
最新版本:memcached-2.1.jar 

操作示例: 
用spymemcached将对象存入缓存 
Java代码   收藏代码
  1. import java.net.InetSocketAddress;  
  2. import java.util.concurrent.Future;  
  3.   
  4. import net.spy.memcached.MemcachedClient;  
  5.   
  6. public class MClient {  
  7.       
  8.     public static void main(String[] args){  
  9.         try{  
  10.             /*建立MemcachedClient 实例,并指定memcached服务的IP地址和端口号*/  
  11.             MemcachedClient mc = new MemcachedClient(new InetSocketAddress("192.168.1.20"12111));  
  12.             Future<Boolean> b = null;  
  13.             /*将key值,过期时间(秒)和要缓存的对象set到memcached中*/  
  14.             b = mc.set("neea:testDaF:ksIdno"900"someObject");  
  15.             if(b.get().booleanValue()==true){  
  16.                 mc.shutdown();  
  17.             }  
  18.         }  
  19.         catch(Exception ex){  
  20.             ex.printStackTrace();  
  21.         }  
  22.     }  
  23. }  


用spymemcached从缓存中取得对象 
Java代码   收藏代码
  1. import java.net.InetSocketAddress;  
  2. import java.util.concurrent.Future;  
  3.   
  4. import net.spy.memcached.MemcachedClient;  
  5.   
  6. public class MClient {  
  7.       
  8.     public static void main(String[] args){  
  9.         try{  
  10.             /*建立MemcachedClient 实例,并指定memcached服务的IP地址和端口号*/  
  11.             MemcachedClient mc = new MemcachedClient(new InetSocketAddress("192.168.1.20"12111));  
  12.             /*按照key值从memcached中查找缓存,不存在则返回null */  
  13. Object b = mc.get("neea:testDaF:ksIdno ");  
  14.             mc.shutdown();  
  15.         }  
  16.         catch(Exception ex){  
  17.             ex.printStackTrace();  
  18.         }  
  19.     }  
  20. }  


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代码

 
 
  1.      
  2. <bean id="cacheManager"    
  3. class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">     
  4. <property name="configLocation">     
  5. <value>classpath:ehcache.xmlvalue     
  6. property     
  7. bean     
  8.  
  9. <bean id="localCache"    
  10. class="org.springframework.cache.ehcache.EhCacheFactoryBean">     
  11. <property name="cacheManager" ref="cacheManager" />     
  12. <property name="cacheName"    
  13. value="×××.cache.LOCAL_CACHE" />     
  14. bean     
  15.  
  16. <bean id="cacheService"    
  17. class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">     
  18. <property name="cacheServerList" value="${cache.servers}"/>     
  19. <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>     
  20. <property name="cacheCluster" value="${cache.cluster}"/>     
  21. <property name="localCache" ref="localCache"/>     
  22. bean    
  23.  
  24. <bean id="cacheManager" 
  25. class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 
  26. <property name="configLocation"> 
  27. <value>classpath:ehcache.xmlvalue 
  28. property 
  29. bean 
  30. <bean id="localCache" 
  31. class="org.springframework.cache.ehcache.EhCacheFactoryBean"> 
  32. <property name="cacheManager" ref="cacheManager" /> 
  33. <property name="cacheName" 
  34. value="×××.cache.LOCAL_CACHE" /> 
  35. bean 
  36.  
  37. <bean id="cacheService" 
  38. class="×××.core.cache.CacheService" init-method="init" destroy-method="destory"> 
  39. <property name="cacheServerList" value="${cache.servers}"/> 
  40. <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/> 
  41. <property name="cacheCluster" value="${cache.cluster}"/> 
  42. <property name="localCache" ref="localCache"/> 
  43. bean 

在properties文件中配置${cache.servers} ${cache.cacheServerWeights} ${cache.cluster}

具体工具类的代码

Java代码

 
 
  1. /**   
  2. * @author Marc   
  3. *    
  4. */    
  5. public class CacheService {     
  6. private Log logger = LogFactory.getLog(getClass());     
  7. private Cache localCache;     
  8. String cacheServerList;     
  9. String cacheServerWeights;     
  10. boolean cacheCluster = false;     
  11. int initialConnections = 10;     
  12. int minSpareConnections = 5;     
  13. int maxSpareConnections = 50;     
  14. long maxIdleTime = 1000 * 60 * 30// 30 minutes    
  15. long maxBusyTime = 1000 * 60 * 5// 5 minutes    
  16. long maintThreadSleep = 1000 * 5// 5 seconds    
  17. int socketTimeOut = 1000 * 3// 3 seconds to block on reads    
  18. int socketConnectTO = 1000 * 3// 3 seconds to block on initial    
  19. // connections. If 0, then will use blocking    
  20. // connect (default)    
  21. boolean failover = false// turn off auto-failover in event of server    
  22. // down    
  23. boolean nagleAlg = false// turn off Nagle's algorithm on all sockets in    
  24. // pool    
  25. MemCachedClient mc;     
  26. public CacheService(){     
  27. mc = new MemCachedClient();     
  28. mc.setCompressEnable(false);     
  29. }     
  30. /**   
  31. * 放入   
  32. *    
  33. */    
  34. public void put(String key, Object obj) {     
  35. Assert.hasText(key);     
  36. Assert.notNull(obj);     
  37. Assert.notNull(localCache);     
  38. if (this.cacheCluster) {     
  39. mc.set(key, obj);     
  40. else {     
  41. Element element = new Element(key, (Serializable) obj);     
  42. localCache.put(element);     
  43. }     
  44. }     
  45. /**   
  46. * 删除    
  47. */    
  48. public void remove(String key){     
  49. Assert.hasText(key);     
  50. Assert.notNull(localCache);     
  51. if (this.cacheCluster) {     
  52. mc.delete(key);     
  53. }else{     
  54. localCache.remove(key);     
  55. }     
  56. }     
  57. /**   
  58. * 得到   
  59. */    
  60. public Object get(String key) {     
  61. Assert.hasText(key);     
  62. Assert.notNull(localCache);     
  63. Object rt = null;     
  64. if (this.cacheCluster) {     
  65. rt = mc.get(key);     
  66. else {     
  67. Element element = null;     
  68. try {     
  69. element = localCache.get(key);     
  70. catch (CacheException cacheException) {     
  71. throw new DataRetrievalFailureException("Cache failure: "    
  72. + cacheException.getMessage());     
  73. }     
  74. if(element != null)     
  75. rt = element.getValue();     
  76. }     
  77. return rt;     
  78. }     
  79. /**   
  80. * 判断是否存在   
  81. *    
  82. */    
  83. public boolean exist(String key){     
  84. Assert.hasText(key);     
  85. Assert.notNull(localCache);     
  86. if (this.cacheCluster) {     
  87. return mc.keyExists(key);     
  88. }else{     
  89. return this.localCache.isKeyInCache(key);     
  90. }     
  91. }     
  92. private void init() {     
  93. if (this.cacheCluster) {     
  94. String[] serverlist = cacheServerList.split(",");     
  95. Integer[] weights = this.split(cacheServerWeights);     
  96. // initialize the pool for memcache servers    
  97. SockIOPool pool = SockIOPool.getInstance();     
  98. pool.setServers(serverlist);     
  99. pool.setWeights(weights);     
  100. pool.setInitConn(initialConnections);     
  101. pool.setMinConn(minSpareConnections);     
  102. pool.setMaxConn(maxSpareConnections);     
  103. pool.setMaxIdle(maxIdleTime);     
  104. pool.setMaxBusyTime(maxBusyTime);     
  105. pool.setMaintSleep(maintThreadSleep);     
  106. pool.setSocketTO(socketTimeOut);     
  107. pool.setSocketConnectTO(socketConnectTO);     
  108. pool.setNagle(nagleAlg);     
  109. pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);     
  110. pool.initialize();     
  111. logger.info("初始化memcached pool!");     
  112. }     
  113. }     
  114.  
  115. private void destory() {     
  116. if (this.cacheCluster) {     
  117. SockIOPool.getInstance().shutDown();     
  118. }     
  119. }     
  120. }    
  121. /**  
  122. * @author Marc  
  123.  
  124. */ 
  125. public class CacheService {  
  126. private Log logger = LogFactory.getLog(getClass());  
  127. private Cache localCache;  
  128. String cacheServerList;  
  129. String cacheServerWeights;  
  130. boolean cacheCluster = false;  
  131. int initialConnections = 10;  
  132. int minSpareConnections = 5;  
  133. int maxSpareConnections = 50;  
  134. long maxIdleTime = 1000 * 60 * 30// 30 minutes  
  135. long maxBusyTime = 1000 * 60 * 5// 5 minutes  
  136. long maintThreadSleep = 1000 * 5// 5 seconds  
  137. int socketTimeOut = 1000 * 3// 3 seconds to block on reads  
  138. int socketConnectTO = 1000 * 3// 3 seconds to block on initial  
  139. // connections. If 0, then will use blocking  
  140. // connect (default)  
  141. boolean failover = false// turn off auto-failover in event of server  
  142. // down  
  143. boolean nagleAlg = false// turn off Nagle's algorithm on all sockets in  
  144. // pool  
  145. MemCachedClient mc;  
  146. public CacheService(){  
  147. mc = new MemCachedClient();  
  148. mc.setCompressEnable(false);  
  149. }  
  150. /**  
  151. * 放入  
  152.  
  153. */ 
  154. public void put(String key, Object obj) {  
  155. Assert.hasText(key);  
  156. Assert.notNull(obj);  
  157. Assert.notNull(localCache);  
  158. if (this.cacheCluster) {  
  159. mc.set(key, obj);  
  160. else {  
  161. Element element = new Element(key, (Serializable) obj);  
  162. localCache.put(element);  
  163. }  
  164. }  
  165. /**  
  166. * 删除   
  167. */ 
  168. public void remove(String key){  
  169. Assert.hasText(key);  
  170. Assert.notNull(localCache);  
  171. if (this.cacheCluster) {  
  172. mc.delete(key);  
  173. }else{  
  174. localCache.remove(key);  
  175. }  
  176. }  
  177. /**  
  178. * 得到  
  179. */ 
  180. public Object get(String key) {  
  181. Assert.hasText(key);  
  182. Assert.notNull(localCache);  
  183. Object rt = null;  
  184. if (this.cacheCluster) {  
  185. rt = mc.get(key);  
  186. else {  
  187. Element element = null;  
  188. try {  
  189. element = localCache.get(key);  
  190. catch (CacheException cacheException) {  
  191. throw new DataRetrievalFailureException("Cache failure: " 
  192. + cacheException.getMessage());  
  193. }  
  194. if(element != null)  
  195. rt = element.getValue();  
  196. }  
  197. return rt;  
  198. }  
  199. /**  
  200. * 判断是否存在  
  201.  
  202. */ 
  203. public boolean exist(String key){  
  204. Assert.hasText(key);  
  205. Assert.notNull(localCache);  
  206. if (this.cacheCluster) {  
  207. return mc.keyExists(key);  
  208. }else{  
  209. return this.localCache.isKeyInCache(key);  
  210. }  
  211. }  
  212. private void init() {  
  213. if (this.cacheCluster) {  
  214. String[] serverlist = cacheServerList.split(",");  
  215. Integer[] weights = this.split(cacheServerWeights);  
  216. // initialize the pool for memcache servers  
  217. SockIOPool pool = SockIOPool.getInstance();  
  218. pool.setServers(serverlist);  
  219. pool.setWeights(weights);  
  220. pool.setInitConn(initialConnections);  
  221. pool.setMinConn(minSpareConnections);  
  222. pool.setMaxConn(maxSpareConnections);  
  223. pool.setMaxIdle(maxIdleTime);  
  224. pool.setMaxBusyTime(maxBusyTime);  
  225. pool.setMaintSleep(maintThreadSleep);  
  226. pool.setSocketTO(socketTimeOut);  
  227. pool.setSocketConnectTO(socketConnectTO);  
  228. pool.setNagle(nagleAlg);  
  229. pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);  
  230. pool.initialize();  
  231. logger.info("初始化memcachedpool!");  
  232. }  
  233. }  
  234. private void destory() {  
  235. if (this.cacheCluster) {  
  236. SockIOPool.getInstance().shutDown();  
  237. }  
  238. }  
  239. }  

然后实现函数的AOP拦截类,用来在函数执行前返回缓存内容

Java代码

 
 
  1. public class CachingInterceptor implements MethodInterceptor {     
  2.  
  3. private CacheService cacheService;     
  4. private String cacheKey;     
  5.  
  6. public void setCacheKey(String cacheKey) {     
  7. this.cacheKey = cacheKey;     
  8. }     
  9.  
  10. public void setCacheService(CacheService cacheService) {     
  11. this.cacheService = cacheService;     
  12. }     
  13.  
  14. public Object invoke(MethodInvocation invocation) throws Throwable {     
  15. Object result = cacheService.get(cacheKey);     
  16. //如果函数返回结果不在Cache中,执行函数并将结果放入Cache    
  17. if (result == null) {     
  18. result = invocation.proceed();     
  19. cacheService.put(cacheKey,result);     
  20. }     
  21. return result;     
  22. }     
  23. }    
  24. public class CachingInterceptor implements MethodInterceptor {  
  25.  
  26. private CacheService cacheService;  
  27. private String cacheKey;  
  28.  
  29. public void setCacheKey(String cacheKey) {  
  30. this.cacheKey = cacheKey;  
  31. }  
  32.  
  33. public void setCacheService(CacheService cacheService) {  
  34. this.cacheService = cacheService;  
  35. }  
  36.  
  37. public Object invoke(MethodInvocation invocation) throws Throwable {  
  38. Object result = cacheService.get(cacheKey);  
  39. //如果函数返回结果不在Cache中,执行函数并将结果放入Cache  
  40. if (result == null) {  
  41. result = invocation.proceed();  
  42. cacheService.put(cacheKey,result);  
  43. }  
  44. return result;  
  45. }  

Spring的AOP配置如下:

Java代码

 
 
  1. <aop:config proxy-target-class="true">     
  2. <aop:advisor     
  3. pointcut="execution(* ×××.PoiService.getOne(..))"    
  4. advice-ref="PoiServiceCachingAdvice" />     
  5. aop:config     
  6.  
  7. <bean id="BasPoiServiceCachingAdvice"    
  8. class="×××.core.cache.CachingInterceptor">     
  9. <property name="cacheKey" value="PoiService" />     
  10. <property name="cacheService" ref="cacheService" />     
  11. bean  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值