Java環境下Memcached應用詳解
本文將對在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>
【編輯推薦】
- .NET分布式緩存之Memcached執行速度檢測
- 從memcached看MySQL和關系數據庫的未來
- 分布式緩存系統memcached簡介與實踐
- Google App Engine的Java持久性與數據存儲
- Java正則表達式實現條件查詢淺析
【責任編輯:彭凡 TEL:(010)68476606】