免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
EHCache技術(shù)文檔
目 錄
0. 文檔介紹... 2
0.1 文檔目的... 2
0.2 文檔范圍... 2
0.3 讀者對(duì)象... 2
0.4 參考文獻(xiàn)... 2
0.5 術(shù)語(yǔ)與縮寫(xiě)解釋... 2
1.    概述... 3
1.1背景... 3
1.2 主要特征.................................................................................................................... 3
1.3環(huán)境... 5
1.4下載資源... 5
2. EHCache頁(yè)面緩存的配置... 5
2.1 EHCache的類層次模型... 5
2.2環(huán)境搭建... 6
2.3 ehcache配置文件中元素說(shuō)明... 8
2.4 在工程中單獨(dú)使用... 10
3. 在Spring中運(yùn)用EHCache. 17
4. 分布式緩存集群環(huán)境配置............................................................................................... 19
4.1  集群配置方式.......................................................................................................... 19
5. 測(cè)試用例...................................................................................................................... 28
文檔介紹
文檔目的
記錄使用EHCache實(shí)現(xiàn)頁(yè)面級(jí)的緩存以及完成集群設(shè)計(jì)的過(guò)程。
文檔范圍
實(shí)現(xiàn)頁(yè)面級(jí)的緩存以及完成集群設(shè)計(jì)的過(guò)程。
0.3 讀者對(duì)象
任何有興趣的家伙。
參考文獻(xiàn)
提示:列出本文檔的所有參考文獻(xiàn)(可以是非正式出版物),格式如下:
[標(biāo)識(shí)符] 作者,文獻(xiàn)名稱,出版單位(或歸屬單位),日期
大部分都是網(wǎng)絡(luò)上查詢的資料,很多,不列舉了。
EHCache簡(jiǎn)介:
http://apps.hi.baidu.com/share/detail/7491847
http://wangjicn.cn/data/read/9082403332378.html
http://blog.csdn.net/mgoann/archive/2009/04/16/4083179.aspx
http://yuanyong.javaeye.com/blog/691499
Spring整合EHCache:
http://wangjicn.cn/data/read/909291257438.html
http://www.yybean.com/ehcache-getting-started-series-5-a-distributed-cache-cluster-environment-configuration
http://zhyt710.javaeye.com/blog/333213
http://tech.ddvip.com/2010-04/1270187299149502.html
http://blog.csdn.net/goodboylllll/archive/2010/04/01/5442329.aspx
術(shù)語(yǔ)與縮寫(xiě)解釋
縮寫(xiě)、術(shù)語(yǔ)
解 釋
EHCache
EHCache是一個(gè)快速的、輕量級(jí)的、易于使用的、進(jìn)程內(nèi)的緩存。它支持read-only和read/write緩存,內(nèi)存和磁盤(pán)緩存。是一個(gè)非常輕量級(jí)的緩存實(shí)現(xiàn),而且從1.2 之后就支持了集群,目前的最新版本是2.1。
背景
系統(tǒng)緩存是位于應(yīng)用程序與物理數(shù)據(jù)源之間,用于臨時(shí)存放復(fù)制數(shù)據(jù)的內(nèi)存區(qū)域,目的是為了減少應(yīng)用程序?qū)ξ锢頂?shù)據(jù)源訪問(wèn)的次數(shù),從而提高應(yīng)用程序的運(yùn)行性能. 緩存設(shè)想內(nèi)存是有限的,緩存的時(shí)效性也是有限的,所以可以設(shè)定內(nèi)存數(shù)量的大小,可以執(zhí)行失效算法 ,可以在內(nèi)存滿了的時(shí)候,按照最少訪問(wèn)等算法將緩存直接移除或切換到硬盤(pán)上。
Ehcache從 Hibernate發(fā)展而來(lái),逐漸涵蓋了Cahce界的全部功能,是目前發(fā)展勢(shì)頭最好的一個(gè)項(xiàng)目。具有快速,簡(jiǎn)單,低消耗,依賴性小,擴(kuò)展性強(qiáng),支持對(duì)象或序列化緩存,支持緩存或元素的失效,提供LRU、LFU和FIFO緩存策略,支持內(nèi)存緩存和磁盤(pán)緩存,分布式緩存機(jī)制等等特點(diǎn)。
Cache 存儲(chǔ)方式 :內(nèi)存或磁盤(pán)。
官方網(wǎng)站:http://ehcache.sourceforge.net/
1. 快速.
2. 簡(jiǎn)單.
3. 多種緩存策略
4. 緩存數(shù)據(jù)有兩級(jí):內(nèi)存和磁盤(pán),因此無(wú)需擔(dān)心容量問(wèn)題
5. 緩存數(shù)據(jù)會(huì)在虛擬機(jī)重啟的過(guò)程中寫(xiě)入磁盤(pán)
6. 可以通過(guò)RMI、可插入API等方式進(jìn)行分布式緩存
7. 具有緩存和緩存管理器的偵聽(tīng)接口
8. 支持多緩存管理器實(shí)例,以及一個(gè)實(shí)例的多個(gè)緩存區(qū)域
9. 提供Hibernate的緩存實(shí)現(xiàn)
1.3 環(huán)境
Windows XP、JDK1.6.03、Tomcat5.5、EHcache2.1
注意:配置好環(huán)境變量。
下載資源
ehcache-2.1.0-distribution.tar.gz:以及 ehcache-web-2.0.2-distribution.tar.gz
http://sourceforge.net/projects/ehcache/
注意:同時(shí)要下載源代碼,部分功能需要修改源代碼,重新做包。
頁(yè)面緩存的配置
EHCache的類層次模型
主要為三層,最上層的是CacheManager,他是操作Ehcache的入口。我們可以通過(guò)CacheManager.getInstance()獲得一個(gè)單子的CacheManger,或者通過(guò)CacheManger的構(gòu)造函數(shù)創(chuàng)建  一個(gè)新的CacheManger。每個(gè)CacheManager都管理著多個(gè)Cache。而每個(gè)Cache都以一種類Hash的方式,關(guān)聯(lián)著多個(gè) Element。Element則是我們用于存放要緩存內(nèi)容的地方。
2.2 環(huán)境搭建
將ehcache-2.1.0-distribution.tar.gz:以及 ehcache-web-2.0.2-distribution.tar.gz解壓得到 需要將它們放置到WEB-INF/lib下。
有一個(gè)重要的配置文件ehcache.xml,可以從ehcache組件包中拷貝一個(gè),也可以自己建立一個(gè)。需要放到classpath下 。常放的路徑為/WEB-INF/classes/ehcache.xml。
2.3 ehcache配置文件中元素說(shuō)明
ehcach.xml配置文件主要參數(shù)的解釋,其實(shí)文件里有詳細(xì)的英文注釋//DiskStore 配置,cache文件的存放目錄 ,主要的值有
* user.home - 用戶主目錄
* user.dir - 用戶當(dāng)前的工作目錄
* java.io.tmpdir - Default temp file path默認(rèn)的temp文件目錄
范例
1、首先設(shè)置EhCache,建立配置文件ehcache.XML,默認(rèn)的位置在class- path,可以放到你的src目錄下:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="Java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000" <!- 緩存最大數(shù)目 ->
eternal="false" <!- 緩存是否持久 ->
overflowToDisk="true" <!- 是否保存到磁盤(pán),當(dāng)系統(tǒng)當(dāng)機(jī)時(shí)->
timeToIdleSeconds="300" <!- 當(dāng)緩存閑置n秒后銷毀 ->
timeToLiveSeconds="180" <!- 當(dāng)緩存存活n秒后銷毀->
diskPersistent="false"
diskExpiryThreadIntervalSeconds= "120"/>
</ehcache>
了解ehcache 的幾個(gè)概念,
1 timeToIdleSeconds ,多長(zhǎng)時(shí)間不訪問(wèn)該緩存,那么ehcache 就會(huì)清除該緩存。
2 timeToLiveSeconds ,緩存的存活時(shí)間,從開(kāi)始創(chuàng)建的時(shí)間算起。
Ehcache的三種清空策略
1 FIFO,first in first out,這個(gè)是大家最熟的,先進(jìn)先出。
2 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點(diǎn)就是講一直以來(lái)最少被使用的。如上面所講,緩存的元素有一個(gè)hit屬性,hit值最小的將會(huì)被清出緩存。
3 LRU,Least Recently Used,最近最少使用的,緩存的元素有一個(gè)時(shí)間戳,當(dāng)緩存容量滿了,而又需要騰出地方來(lái)緩存新的元素的時(shí)候,那么現(xiàn)有緩存元素中時(shí)間戳離當(dāng)前時(shí)間最遠(yuǎn)的元素將被清出緩存。
首頁(yè)的頁(yè)面緩存
一個(gè)網(wǎng)站的首頁(yè)估計(jì)是被訪問(wèn)的次數(shù)最多的,我們可以考慮給首頁(yè)做一個(gè)頁(yè)面緩存
緩存策略:我認(rèn)為應(yīng)該是某個(gè)固定時(shí)間之內(nèi)不變的,比如說(shuō)2分鐘更新一次,以應(yīng)用結(jié)構(gòu)page-filter-action-service-dao-db 為例。
位置:頁(yè)面緩存做到盡量靠近客戶的地方,就是在page和filter之間 ,這樣的優(yōu)點(diǎn)就是第一個(gè)用戶請(qǐng)求之后,頁(yè)面被緩存,第二個(gè)用戶再來(lái)請(qǐng)求的時(shí)候,走到filter這個(gè)請(qǐng)求就結(jié)束了,無(wú)需再走后面的action- service-dao-db。帶來(lái)的好處是服務(wù)器壓力的減低和客戶段頁(yè)面響應(yīng)速度的加快。
首頁(yè)的頁(yè)面緩存的存活時(shí)間,我們定的是2 分鐘,那么也就是說(shuō)我們的timeToLiveSeconds 應(yīng)該設(shè)置為120 ,同時(shí)我們的timeToIdleSeconds 最好也設(shè)置為2 分鐘,或者小于2 分鐘。我們來(lái)看一下下面這個(gè)配置,這個(gè)配置片段應(yīng)該放到ehcache.xml中:
SimplePageCachingFilter 是緩存的名字,maxElementsInMemory 表示內(nèi)存中SimplePageCachingFilter 緩存中元素的最大數(shù)量為10,maxElementsOnDisk 是指持久化該緩存的元素到硬盤(pán)上的最大數(shù)量也為10 (),eternal=false 意味著該緩存會(huì)死亡。overflowToDisk=true 意思是表示當(dāng)緩存中元素的數(shù)量超過(guò)限制時(shí),就把這些元素持久化到硬盤(pán),如果overflowToDisk 是false ,那么maxElementsOnDisk 的設(shè)置就沒(méi)有什么意義了。memoryStoreEvictionPolicy=LFU 是指按照緩存的hit 值來(lái)清除,也就是說(shuō)緩存滿了之后,新的對(duì)象需要緩存時(shí),將會(huì)將緩存中hit 值最小的對(duì)象清除出緩存,給新的對(duì)象騰出地方來(lái)了。
接著我們來(lái)看一下SimplePageCachingFilter的配置,
XML/HTML代碼
<filter>
<filter-name>indexCacheFilterfilter-name>
<filter-class>
net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
<filter-class>
<filter>
<filter-mapping>
<filter-name>indexCacheFilterfilter-name>
<url-pattern>*index.action</url-pattern>
<filter-mapping>
就只需要這么多步驟,我們就可以給某個(gè)頁(yè)面做一個(gè)緩存的,把上面這段配置放到你的web.xml中,那么當(dāng)你打開(kāi)首頁(yè)的時(shí)候,你會(huì)發(fā)現(xiàn),2分鐘才會(huì)有一堆sql語(yǔ)句出現(xiàn)在控制臺(tái)上。當(dāng)然你也可以調(diào)成5分鐘,總之一切都在控制中。
好了,緩存整個(gè)頁(yè)面看上去是非常的簡(jiǎn)單,甚至都不需要寫(xiě)一行代碼,只需要幾行配置就行了,夠簡(jiǎn)單吧,雖然看上去簡(jiǎn)單,但是事實(shí)上內(nèi)部實(shí)現(xiàn)卻不簡(jiǎn)單哦,有興趣的話,大家可以看看SimplePageCachingFilter繼承體系的源代碼。
上面的配置針對(duì)的情況是緩存首頁(yè)的全部,如果你只想緩存首頁(yè)的部分內(nèi)容時(shí),你需要使用SimplePageFragmentCachingFilter這個(gè)filter。我們看一下如下片斷:
XML/HTML代碼
<filter>
<filter-name>indexCacheFilterfilter-name>
<filter-class>
net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter
<filter-class>
filter>
<filter-mapping>
<filter-name>indexCacheFilterfilter-name>
<url-pattern>*/index_right.jsp</url-pattern>
<filter-mapping>
這個(gè)jsp需要被jsp:include到其他頁(yè)面,這樣就做到的局部頁(yè)面的緩存。這一點(diǎn)貌似沒(méi)有oscache的tag好用。
事實(shí)上在cachefilter中還有一個(gè)特性,就是gzip,也就是說(shuō)緩存中的元素是被壓縮過(guò)的,如果客戶瀏覽器支持壓縮的話,filter會(huì)直接返回壓縮過(guò)的流,這樣節(jié)省了帶寬,把解壓的工作交給了客戶瀏覽器,如果客戶的瀏覽器不支持gzip,那么filter會(huì)把緩存的元素拿出來(lái)解壓后再返回給客戶瀏覽器(大多數(shù)爬蟲(chóng)是不支持gzip的,所以filter也會(huì)解壓后再返回流),這樣做的優(yōu)點(diǎn)是節(jié)省帶寬,缺點(diǎn)就是增加了客戶瀏覽器的負(fù)擔(dān)(但是我覺(jué)得對(duì)當(dāng)代的計(jì)算機(jī)而言,這個(gè)負(fù)擔(dān)微乎其微)。
好了,如果你的頁(yè)面正好也需要用到頁(yè)面緩存,不防可以考慮一下ehcache,因?yàn)樗鼘?shí)在是非常簡(jiǎn)單,而且易用。
總結(jié):ehcache是一個(gè)非常輕量級(jí)的緩存實(shí)現(xiàn),而且從1.2之后就支持了集群,目前的最新版本是1.3,而且是hibernate默認(rèn)的緩存provider。雖然本文是介紹的是ehcache對(duì)頁(yè)面緩存的支持,但是ehcache的功能遠(yuǎn)不止如此,當(dāng)然要使用好緩存,對(duì)JEE中緩存的原理,使用范圍,適用場(chǎng)景等等都需要有比較深刻的理解,這樣才能用好緩存,用對(duì)緩存。
最后復(fù)習(xí)一下ehcache中緩存的3種清空策略:
1 FIFO,first in first out,這個(gè)是大家最熟的,先進(jìn)先出,不多講了
2 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點(diǎn)就是講一直以來(lái)最少被使用的。如上面所講,緩存的元素有一個(gè)hit屬性,hit值最小的將會(huì)被清出緩存。
2 LRU,Least Recently Used,最近最少使用的,緩存的元素有一個(gè)時(shí)間戳,當(dāng)緩存容量滿了,而又需要騰出地方來(lái)緩存新的元素的時(shí)候,那么現(xiàn)有緩存元素中時(shí)間戳離當(dāng)前時(shí)間最遠(yuǎn)的元素將被清出緩存。
2.4 在工程中單獨(dú)使用
1.創(chuàng)建CacheManager (net.sf.ehcache.CacheManager)
(1)使用默認(rèn)配置文件創(chuàng)建
CacheManager manager = CacheManager.create();
(2)使用指定配置文件創(chuàng)建
CacheManager manager = CacheManager.create("src/config/ehcache.xml");
(3)從classpath找尋配置文件并創(chuàng)建
URL url = getClass().getResource("/anothername.xml");
CacheManager manager = CacheManager.create(url);
(4)通過(guò)輸入流創(chuàng)建
InputStream fis = new FileInputStream(new File("src/config/ehcache.xml").getAbsolutePath());
try { manager = CacheManager.create(fis); } finally { fis.close(); }
2.創(chuàng)建Caches (net.sf.ehcache.Cache)
(1)取得配置文件中預(yù)先 定義的sampleCache1設(shè)置,生成一個(gè)Cache
Cache cache = manager.getCache("sampleCache1");
(2)設(shè)置一個(gè)名為test 的新cache,test屬性為默認(rèn)
CacheManager manager = CacheManager.create();
manager.addCache("test");
(3)設(shè)置一個(gè)名為test 的新cache,并定義其屬性
CacheManager manager = CacheManager.create();
Cache cache = new Cache("test", 1, true, false, 5, 2);
manager.addCache(cache);
(4)刪除cache
CacheManager singletonManager = CacheManager.create();
singletonManager.removeCache("sampleCache1");
3.使用Caches
(1)往cache中加入元素
Element element = new Element("key1", "value1");
cache.put(new Element(element);
(2)從cache中取得元素
Element element = cache.get("key1");
(3)從cache中刪除元素
Cache cache = manager.getCache("sampleCache1");
Element element = new Element("key1", "value1");
cache.remove("key1");
3.卸載CacheManager ,關(guān)閉Cache
manager.shutdown();
在Spring中運(yùn)用EHCache
需要使用Spring來(lái)實(shí)現(xiàn)一個(gè)Cache簡(jiǎn)單的解決方案,具體需求如下:使用任意一個(gè)現(xiàn)有開(kāi)源Cache Framework,要求可以Cache系統(tǒng)中Service或則DAO層的get/find等方法返回結(jié)果,如果數(shù)據(jù)更新(使用Create/update/delete方法),則刷新cache中相應(yīng)的內(nèi)容。
根據(jù)需求,計(jì)劃使用Spring AOP + ehCache來(lái)實(shí)現(xiàn)這個(gè)功能,采用ehCache原因之一是Spring提供了ehCache的支持,至于為何僅僅支持ehCache而不支持osCache和JBossCache無(wú)從得知(Hibernate???),但畢竟Spring提供了支持,可以減少一部分工作量:)。二是后來(lái)實(shí)現(xiàn)了OSCache和JBoss Cache的方式后,經(jīng)過(guò)簡(jiǎn)單測(cè)試發(fā)現(xiàn)幾個(gè)Cache在效率上沒(méi)有太大的區(qū)別(不考慮集群),決定采用ehCahce。
AOP嘛,少不了攔截器,先創(chuàng)建一個(gè)實(shí)現(xiàn)了MethodInterceptor接口的攔截器,用來(lái)攔截Service/DAO的方法調(diào)用,攔截到方法后,搜索該方法的結(jié)果在cache中是否存在,如果存在,返回cache中的緩存結(jié)果,如果不存在,返回查詢數(shù)據(jù)庫(kù)的結(jié)果,并將結(jié)果緩存到cache中。
MethodCacheInterceptor.java
Java代碼
package com.co.cache.ehcache;
import java.io.Serializable;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean
{
private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);
private Cache cache;
public void setCache(Cache cache) {
this.cache = cache;
}
public MethodCacheInterceptor() {
super();
}
/**
* 攔截Service/DAO的方法,并查找該結(jié)果是否存在,如果存在就返回cache中的值,
* 否則,返回?cái)?shù)據(jù)庫(kù)查詢結(jié)果,并將查詢結(jié)果放入cache
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
String targetName = invocation.getThis().getClass().getName();
String methodName = invocation.getMethod().getName();
Object[] arguments = invocation.getArguments();
Object result;
logger.debug("Find object from cache is " + cache.getName());
String cacheKey = getCacheKey(targetName, methodName, arguments);
Element element = cache.get(cacheKey);
if (element == null) {
logger.debug("Hold up method , Get method result and create cache........!");
result = invocation.proceed();
element = new Element(cacheKey, (Serializable) result);
cache.put(element);
}
return element.getValue();
}
/**
* 獲得cache key的方法,cache key是Cache中一個(gè)Element的唯一標(biāo)識(shí)
* cache key包括 包名+類名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser
*/
private String getCacheKey(String targetName, String methodName, Object[] arguments) {
StringBuffer sb = new StringBuffer();
sb.append(targetName).append(".").append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (int i = 0; i < arguments.length; i++) {
sb.append(".").append(arguments[i]);
}
}
return sb.toString();
}
/**
* implement InitializingBean,檢查cache是否為空
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");
}
}
上面的代碼中可以看到,在方法public Object invoke(MethodInvocation invocation) 中,完成了搜索Cache/新建cache的功能。
Java代碼
Element element = cache.get(cacheKey);
這句代碼的作用是獲取cache中的element,如果cacheKey所對(duì)應(yīng)的element不存在,將會(huì)返回一個(gè)null值
Java代碼
result = invocation.proceed();
這句代碼的作用是獲取所攔截方法的返回值,詳細(xì)請(qǐng)查閱AOP相關(guān)文檔。
隨后,再建立一個(gè)攔截器MethodCacheAfterAdvice,作用是在用戶進(jìn)行create/update/delete操作時(shí)來(lái)刷新/remove相關(guān)cache內(nèi)容,這個(gè)攔截器實(shí)現(xiàn)了AfterReturningAdvice接口,將會(huì)在所攔截的方法執(zhí)行后執(zhí)行在public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3)方法中所預(yù)定的操作
Java代碼
package com.co.cache.ehcache;
import java.lang.reflect.Method;
import java.util.List;
import net.sf.ehcache.Cache;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
public class MethodCacheAfterAdvice implements AfterReturningAdvice, InitializingBean
{
private static final Log logger = LogFactory.getLog(MethodCacheAfterAdvice.class);
private Cache cache;
public void setCache(Cache cache) {
this.cache = cache;
}
public MethodCacheAfterAdvice() {
super();
}
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
String className = arg3.getClass().getName();
List list = cache.getKeys();
for(int i = 0;i<list.size();i++){
String cacheKey = String.valueOf(list.get(i));
if(cacheKey.startsWith(className)){
cache.remove(cacheKey);
logger.debug("remove cache " + cacheKey);
}
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");
}
}
上面的代碼很簡(jiǎn)單,實(shí)現(xiàn)了afterReturning方法實(shí)現(xiàn)自AfterReturningAdvice接口,方法中所定義的內(nèi)容將會(huì)在目標(biāo)方法執(zhí)行后執(zhí)行,在該方法中 的作用是獲取目標(biāo)class的全名,如:com.co.cache.test.TestServiceImpl,然后循環(huán)cache的key list,remove cache中所有和該class相關(guān)的element。
Java代碼
String className = arg3.getClass().getName();
隨后,開(kāi)始配置ehCache的屬性,ehCache需要一個(gè)xml文件來(lái)設(shè)置ehCache相關(guān)的一些屬性,如最大緩存數(shù)量、cache刷新的時(shí)間等等.
ehcache.xml
Java代碼
<ehcache>
<diskStore path="c:\\myapp\\cache"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<cache name="DEFAULT_CACHE"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300000"
timeToLiveSeconds="600000"
overflowToDisk="true"
/>
</ehcache>
配置每一項(xiàng)的詳細(xì)作用不再詳細(xì)解釋,有興趣的請(qǐng)google下  ,這里需要注意一點(diǎn)defaultCache標(biāo)簽定義了一個(gè)默認(rèn)的Cache,這個(gè)Cache是不能刪除的,否則會(huì)拋出No default cache is configured異常。另外,由于使用攔截器來(lái)刷新Cache內(nèi)容,因此在定義cache生命周期時(shí)可以定義較大的數(shù)值,timeToIdleSeconds="300000" timeToLiveSeconds="600000",好像還不夠大?
然后,在將Cache和兩個(gè)攔截器配置到Spring,這里沒(méi)有使用2.0里面AOP的標(biāo)簽。
cacheContext.xml
Java代碼
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 引用ehCache的配置 -->
<bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>ehcache.xml</value>
</property>
</bean>
<!-- 定義ehCache的工廠,并設(shè)置所使用的Cache name -->
<bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="defaultCacheManager"/>
</property>
<property name="cacheName">
<value>DEFAULT_CACHE</value>
</property>
</bean>
<!-- find/create cache攔截器 -->
<bean id="methodCacheInterceptor" class="com.co.cache.ehcache.MethodCacheInterceptor">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>
<!-- flush cache攔截器 -->
<bean id="methodCacheAfterAdvice" class="com.co.cache.ehcache.MethodCacheAfterAdvice">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>
<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="methodCacheInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*find.*</value>
<value>.*get.*</value>
</list>
</property>
</bean>
<bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="methodCacheAfterAdvice"/>
</property>
<property name="patterns">
<list>
<value>.*create.*</value>
<value>.*update.*</value>
<value>.*delete.*</value>
</list>
</property>
</bean>
</beans>
上面的代碼最終創(chuàng)建了兩個(gè)"切入點(diǎn)",methodCachePointCut和methodCachePointCutAdvice,分別用于攔截不同方法名的方法,可以根據(jù)需要任意增加所需要攔截方法的名稱。
需要注意的是
Java代碼
<bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="defaultCacheManager"/>
</property>
<property name="cacheName">
<value>DEFAULT_CACHE</value>
</property>
</bean>
如果cacheName屬性內(nèi)設(shè)置的name在ehCache.xml中無(wú)法找到,那么將使用默認(rèn)的cache(defaultCache標(biāo)簽定義).
事實(shí)上到了這里,一個(gè)簡(jiǎn)單的Spring + ehCache Framework基本完成了,為了測(cè)試效果,舉一個(gè)實(shí)際應(yīng)用的例子,定義一個(gè)TestService和它的實(shí)現(xiàn)類TestServiceImpl,里面包含
兩個(gè)方法getAllObject()和updateObject(Object Object),具體代碼如下
TestService.java
Java代碼
package com.co.cache.test;
import java.util.List;
public interface TestService {
public List getAllObject();
public void updateObject(Object Object);
}
TestServiceImpl.java
Java代碼
package com.co.cache.test;
import java.util.List;
public class TestServiceImpl implements TestService
{
public List getAllObject() {
System.out.println("---TestService:Cache內(nèi)不存在該element,查找并放入Cache!");
return null;
}
public void updateObject(Object Object) {
System.out.println("---TestService:更新了對(duì)象,這個(gè)Class產(chǎn)生的cache都將被remove!");
}
}
使用Spring提供的AOP進(jìn)行配置
applicationContext.xml
XML/HTML代碼
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="cacheContext.xml"/>
<bean id="testServiceTarget" class="com.co.cache.test.TestServiceImpl"/>
<bean id="testService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="testServiceTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>methodCachePointCut</value>
<value>methodCachePointCutAdvice</value>
</list>
</property>
</bean>
</beans>
這里一定不能忘記import cacheContext.xml文件,不然定義的兩個(gè)攔截器就沒(méi)辦法使用了。
最后,寫(xiě)一個(gè)測(cè)試的代碼
MainTest.java
Java代碼
(DEFAULT_CONTEXT_FILE);
TestService testService = (TestService)context.getBean("testService");
System.out.println("1--第一次查找并創(chuàng)建cache");
testService.getAllObject();
System.out.println("2--在cache中查找");
testService.getAllObject();
System.out.println("3--remove cache");
testService.updateObject(null);
System.out.println("4--需要重新查找并創(chuàng)建cache");
testService.getAllObject();
}
}
運(yùn)行,結(jié)果如下
Java代碼
1--第一次查找并創(chuàng)建cache
---TestService:Cache內(nèi)不存在該element,查找并放入Cache!
2--在cache中查找
3--remove cache
---TestService:更新了對(duì)象,這個(gè)Class產(chǎn)生的cache都將被remove!
4--需要重新查找并創(chuàng)建cache
---TestService:Cache內(nèi)不存在該element,查找并放入Cache!
大功告成  .可以看到,第一步執(zhí)行g(shù)etAllObject(),執(zhí)行TestServiceImpl內(nèi)的方法,并創(chuàng)建了cache,在第二次執(zhí)行g(shù)etAllObject()方法時(shí),由于cache有該方法的緩存,直接從cache中g(shù)et出方法的結(jié)果,所以沒(méi)有打印出TestServiceImpl中的內(nèi)容,而第三步,調(diào)用了updateObject方法,和TestServiceImpl相關(guān)的cache被remove,所以在第四步執(zhí)行時(shí),又執(zhí)行TestServiceImpl中的方法,創(chuàng)建Cache。
網(wǎng)上也有不少類似的例子,但是很多都不是很完備,自己參考了一些例子的代碼,其實(shí)在spring-modules中也提供了對(duì)幾種cache的支持,ehCache,OSCache,JBossCache這些,看了一下,基本上都是采用類似的方式,只不過(guò)封裝的更完善一些,主要思路也還是Spring的AOP,有興趣的可以研究一下。
4. 分布式緩存集群環(huán)境配置
4.1集群配置方式
ehcache提供三種網(wǎng)絡(luò)連接策略來(lái)實(shí)現(xiàn)集群,rmi,jgroup還有jms。這里只說(shuō)rmi方式。同時(shí)ehcache可以可以實(shí)現(xiàn)多播的方式實(shí)現(xiàn)集群。也可以手動(dòng)指定集群主機(jī)序列實(shí)現(xiàn)集群,本例應(yīng)用手動(dòng)指定。
這里說(shuō)點(diǎn)題外話,本來(lái)看著分發(fā)包中的原來(lái)的例子配置是一件不怎么難的事情,應(yīng)該很容易就能實(shí)現(xiàn)。但是一開(kāi)始,我是在我的linux主機(jī)上和我的主操作系統(tǒng)windows上實(shí)現(xiàn)集群配置。結(jié)果反過(guò)來(lái)弄過(guò)去,都沒(méi)有成功。然后在網(wǎng)上找一些別人的配置經(jīng)驗(yàn),竟然都是配置片段,沒(méi)有完整的實(shí)例文件。結(jié)果配置半天沒(méi)成功。但我懷疑是我的linux系統(tǒng)有些地方可能沒(méi)有配置好,于是先不管他。有開(kāi)啟了我的另一個(gè)windows主機(jī)。然后把程序部署上去,竟然一次試驗(yàn)成功。高興的同時(shí),我得發(fā)句話“不要把代碼片段稱作實(shí)例,這很不負(fù)責(zé)任”。同時(shí)還存在一個(gè)問(wèn)題,在linux下沒(méi)有部署成功的原因有待查明。
具體說(shuō)明:配置cacheManagerPeerListenerFactory是配宿主主機(jī)配置監(jiān)聽(tīng)程序,來(lái)發(fā)現(xiàn)其他主機(jī)發(fā)來(lái)的同步請(qǐng)求配置cacheManagerPeerProviderFactory是指定除自身之外的網(wǎng)絡(luò)群體中其他提供同步的主機(jī)列表,用“|”分開(kāi)不同的主機(jī)。
下面的例子的測(cè)試過(guò)程是:主機(jī)B緩存開(kāi)啟,并從名為UserCache的緩存中循環(huán)抓取鍵值為“key1”的元素,直到取到,才退出循環(huán)。主機(jī)A緩存啟動(dòng),并在名為UserCache的緩存中放入鍵值為“key1”的元素。顯然,如果主機(jī)B取到的元素,那么就證明同步成功,也就是集群成功。所以在測(cè)試過(guò)程中先啟動(dòng)主機(jī)B的測(cè)試程序,在啟動(dòng)主機(jī)A的測(cè)試程序。
下面具體說(shuō)配置文件以及測(cè)試程序:
1. 主機(jī)A的配置文件以及測(cè)試源代碼
config/ehcache_cluster.xml
Xml代碼
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//192.168.1.254:40000/UserCache" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.126,port=40000,socketTimeoutMillis=120000" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</defaultCache>
<cache name="UserCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="100000" timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</cache>
</ehcache>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//192.168.1.254:40000/UserCache" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.126,port=40000,socketTimeoutMillis=120000" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</defaultCache>
<cache name="UserCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="100000" timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</cache>
</ehcache>
tutorial/UsingCacheCluster
Java代碼
package tutorial;
import java.net.URL;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
public class UsingCacheCluster {
public static void main(String[] args) throws Exception {
URL url = UsingCacheCluster.class.getClassLoader().getResource(
"config/ehcache_cluster.xml");
CacheManager manager = new CacheManager(url);
//取得Cache
Cache cache = manager.getCache("UserCache");
Element element = new Element("key1", "value1");
cache.put(element);
Element element1 = cache.get("key1");
System.out.println(element1.getValue());
}
}
2.  主機(jī)B上的配置文件以及測(cè)試代碼
config/ehcache_cluster.xml
Xml代碼
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//192.168.1.126:40000/UserCache" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.254,port=40000, socketTimeoutMillis=120000" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</defaultCache>
<cache name="UserCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="100000" timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</cache>
</ehcache>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//192.168.1.126:40000/UserCache" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.254,port=40000, socketTimeoutMillis=120000" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</defaultCache>
<cache name="UserCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="100000" timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
</cache>
</ehcache>
tutorial/UsingCacheCluster
Java代碼
package tutorial;
import java.net.URL;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
public class UsingCacheCluster {
public static void main(String[] args) throws Exception {
URL url = UsingCacheCluster.class.getClassLoader().getResource(
"config/ehcache_cluster.xml");
CacheManager manager = new CacheManager(url);
//取得Cache
Cache cache = manager.getCache("UserCache");
while(true) {
Element e = cache.get("key1");
if(e != null) {
System.out.println(e.getValue());
break;
}
Thread.sleep(1000);
}
}
}
5. 測(cè)試用例
直接進(jìn)入測(cè)試文檔EHCache測(cè)試文檔.docx
分布式同步緩存要讓這邊的cache知道對(duì)方的cache,叫做Peer Discovery(成員發(fā)現(xiàn))
EHCache實(shí)現(xiàn)成員發(fā)現(xiàn)的方式有兩種:
第一,自動(dòng)查找
自動(dòng)的發(fā)現(xiàn)方式用 TCP 廣播機(jī)制來(lái)確定和維持一個(gè)廣播組。它只需要一個(gè)簡(jiǎn)單的配置可以自動(dòng)的在組中添加和移除成員。在集群中也不需要什么優(yōu)化服務(wù)器的知識(shí),這是默認(rèn)推薦的。
成員每秒向群組發(fā)送一個(gè)“心跳”。如果一個(gè)成員 5 秒種都沒(méi)有發(fā)出信號(hào)它將被群組移除。如果一個(gè)新的成員發(fā)送了一個(gè)“心跳”它將被添加進(jìn)群組。
任何一個(gè)用這個(gè)配置安裝了復(fù)制功能的 cache 都將被其他的成員發(fā)現(xiàn)并標(biāo)識(shí)為可用狀態(tài)。
要設(shè)置自動(dòng)的成員發(fā)現(xiàn),需要指定ehcache配置文件中cacheManagerPeerProviderFactory元素的 properties屬性,就像下面這樣:
peerDiscovery=automatic multicastGroupAddress=multicast address | multicast host name
multicastGroupPort=port timeToLive=0-255 (timeToLive屬性詳見(jiàn)常見(jiàn)問(wèn)題部分的描述)
示例
假設(shè)你在集群中有兩臺(tái)服務(wù)器。你希望同步 sampleCache1 和 sampleCache2。每臺(tái)獨(dú)立的服務(wù)器都要有這樣的配置:
配置 server1和 server2
Xml代碼  
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"/>
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"/>
第二,手動(dòng)查找
進(jìn)行手動(dòng)成員配置要知道每個(gè)監(jiān)聽(tīng)器的 IP 地址和端口。成員不能在運(yùn)行時(shí)動(dòng)態(tài)地添加和移除。在技術(shù)上很難使用廣播的情況下就可以手動(dòng)成員發(fā)現(xiàn),例如在集群的服務(wù)器之間有一個(gè)不能傳送廣播報(bào)文的路由器。你也可以用手動(dòng)成員發(fā)現(xiàn)進(jìn)行單向的數(shù)據(jù)復(fù)制,只讓server2 知道 server1而 server1 不知道 server2。
配置手動(dòng)成員發(fā)現(xiàn),需要指定 ehcache 配置文件中 cacheManagerPeerProviderFactory 的properties屬性,像下面這樣:
peerDiscovery=manual rmiUrls=//server:port/cacheName, ... rmiUrls 配置的是服務(wù)器 cache peers 的列表。注意不要重復(fù)配置。
示例
假設(shè)你在集群中有兩臺(tái)服務(wù)器。你要同步 sampleCache1 和 sampleCache2。下面是每個(gè)
服務(wù)器需要的配置:
配置 server1
Xml代碼  
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>
配置 server2
Xml代碼  
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>
給個(gè)完整的配置:
Xml代碼  
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory class=
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//10.129.0.203:40000/UserCache |//10.129.0.203:40000/ReturnCache"/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=10.129.0.202,port=40000, socketTimeoutMillis=120000"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskSpoolBufferSizeMB="30"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
/>
<cache name="UserCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="100000"
timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
</cache>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerPeerProviderFactory class=
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//10.129.0.203:40000/UserCache |//10.129.0.203:40000/ReturnCache"/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=10.129.0.202,port=40000, socketTimeoutMillis=120000"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskSpoolBufferSizeMB="30"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
/>
<cache name="UserCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="100000"
timeToLiveSeconds="100000"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
</cache>
引用
屬性解釋:
必須屬性:
name:設(shè)置緩存的名稱,用于標(biāo)志緩存,惟一
maxElementsInMemory:在內(nèi)存中最大的對(duì)象數(shù)量
maxElementsOnDisk:在DiskStore中的最大對(duì)象數(shù)量,如為0,則沒(méi)有限制
eternal:設(shè)置元素是否永久的,如果為永久,則timeout忽略
overflowToDisk:是否當(dāng)memory中的數(shù)量達(dá)到限制后,保存到Disk
可選的屬性:
timeToIdleSeconds:設(shè)置元素過(guò)期前的空閑時(shí)間
timeToLiveSeconds:設(shè)置元素過(guò)期前的活動(dòng)時(shí)間
diskPersistent:是否disk store在虛擬機(jī)啟動(dòng)時(shí)持久化。默認(rèn)為false
diskExpiryThreadIntervalSeconds:運(yùn)行disk終結(jié)線程的時(shí)間,默認(rèn)為120秒
memoryStoreEvictionPolicy:策略關(guān)于Eviction
緩存子元素:
cacheEventListenerFactory:注冊(cè)相應(yīng)的的緩存監(jiān)聽(tīng)類,用于處理緩存事件,如put,remove,update,和expire
bootstrapCacheLoaderFactory:指定相應(yīng)的BootstrapCacheLoader,用于在初始化緩存,以及自動(dòng)設(shè)置。
集群的作用有兩方面吧,第一,負(fù)載分流。第二,安全性。
在我看來(lái),如果一個(gè)web應(yīng)用的訪問(wèn)量不是很多的話,集群和非集群的效果相差不了多少,甚至有的時(shí)候集群會(huì)消耗更多的資源,導(dǎo)致垃圾回收頻繁,內(nèi)存占用率高等的現(xiàn)象。當(dāng)然,如果訪問(wèn)量大,那當(dāng)然是集群的效果會(huì)好很多。
那在訪問(wèn)量小的時(shí)候是不是就不用做集群呢,答案是否定的。集群的另外一個(gè)好處就是數(shù)據(jù)和狀態(tài)的安全性,EHCache會(huì)自動(dòng)同步集群中服務(wù)器的緩存,當(dāng)一 臺(tái)服務(wù)器掛掉后,另外的服務(wù)器可以馬上接上來(lái),防止用戶狀態(tài)數(shù)據(jù)丟失,所以,對(duì)安全性的保障是十分有效的。
ehcache提供三種網(wǎng)絡(luò)連接策略來(lái)實(shí)現(xiàn)集群,rmi,jgroup還有jms。同時(shí)ehcache可以可以實(shí)現(xiàn)多播的方式實(shí)現(xiàn)集群,也可以手動(dòng)指定集群主機(jī)序列實(shí)現(xiàn)集群。
首推薦官方文檔:http://ehcache.org/documentation/distributed_caching.html
下面是來(lái)自javaeye的一篇文章,略有補(bǔ)充,算是實(shí)踐總結(jié)吧
Ehcache支持的分布式緩存支持有三種RMI,JGroups,JMS,這里介紹下MRI和JGrpups兩種方式,Ehcache使用版本為1.5.0,關(guān)于ehcache的其他信息請(qǐng)參考http://ehcache.sourceforge.net/EhcacheUserGuide.html
關(guān)于jgroups的信息請(qǐng)參考http://www.jgroups.org/manual/html_single/index.html。
環(huán)境為兩臺(tái)機(jī)器 server1 ip:192.168.2.154,server2 ip:192.168.2.23
1. RMI方式:
rmi的方式配置要點(diǎn)(下面均是server1上的配置,server2上的只需要把ip兌換即可)
a. 配置PeerProvider:
Xml代碼
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual,rmiUrls=//192.168.2.23:40001/userCache|//192.168.2.23:40001/resourceCache" />
配置中通過(guò)手動(dòng)方式同步sever2中的userCache和resourceCache。
b. 配置CacheManagerPeerListener:
Xml代碼
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="hostName=192.168.2.154, port=40001,socketTimeoutMillis=2000" />
配置中server1監(jiān)聽(tīng)本機(jī)40001端口。
c. 在每一個(gè)cache中添加cacheEventListener,例子如下:
Xml代碼
<cache name="userCache" maxElementsInMemory="10000" eternal="true" overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0" diskPersistent="false" diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"     properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,replicateUpdatesViaCopy= false, replicateRemovals= true " /></cache>
屬性解釋:
必須屬性:
name:設(shè)置緩存的名稱,用于標(biāo)志緩存,惟一
maxElementsInMemory:在內(nèi)存中最大的對(duì)象數(shù)量
maxElementsOnDisk:在DiskStore中的最大對(duì)象數(shù)量,如為0,則沒(méi)有限制
eternal:設(shè)置元素是否永久的,如果為永久,則timeout忽略
overflowToDisk:是否當(dāng)memory中的數(shù)量達(dá)到限制后,保存到Disk
可選的屬性:
timeToIdleSeconds:設(shè)置元素過(guò)期前的空閑時(shí)間
timeToLiveSeconds:設(shè)置元素過(guò)期前的活動(dòng)時(shí)間
diskPersistent:是否disk store在虛擬機(jī)啟動(dòng)時(shí)持久化。默認(rèn)為false
diskExpiryThreadIntervalSeconds:運(yùn)行disk終結(jié)線程的時(shí)間,默認(rèn)為120秒
memoryStoreEvictionPolicy:策略關(guān)于Eviction
緩存子元素:
cacheEventListenerFactory:注冊(cè)相應(yīng)的的緩存監(jiān)聽(tīng)類,用于處理緩存事件,如put,remove,update,和expire
bootstrapCacheLoaderFactory:指定相應(yīng)的BootstrapCacheLoader,用于在初始化緩存,以及自動(dòng)設(shè)置。
參考另外一篇學(xué)習(xí)筆記http://wozailongyou.javaeye.com/blog/230252,也有集群的說(shuō)明
2. JGroups方式:
ehcache 1.5.0之后版本支持的一種方式,配置起來(lái)比較簡(jiǎn)單,要點(diǎn):
a. 配置PeerProvider,使用tcp的方式,例子如下:
Xml代碼
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"        properties="connect=TCP(start_port=7800):        TCPPING(initial_hosts=192.168.2.154[7800],192.168.2.23[7800];port_range=10;timeout=3000;        num_initial_members=3;up_thread=true;down_thread=true):        VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):        pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_timeout=3000):        pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;        print_local_addr=false;down_thread=true;up_thread=true)"         propertySeparator="::" />
b.為每個(gè)cache添加cacheEventListener:
Xml代碼
<cache name="userCache" maxElementsInMemory="10000" eternal="true"        overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"        diskPersistent="false" diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"            properties="replicateAsynchronously=true, replicatePuts=true,                   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/></cache>
JGroup方式配置的兩個(gè)server上的配置文件一樣,若有多個(gè)server,在initial_hosts中將server ip加上即可。
一個(gè)完整的ehcache.xml文件:
Xml代碼
<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="http://ehcache.sf.net/ehcache.xsd">    <diskStore path="java.io.tmpdir" />     <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"        properties="connect=TCP(start_port=7800):        TCPPING(initial_hosts=192.168.2.154[7800],192.168.2.23[7800];port_range=10;timeout=3000;        num_initial_members=3;up_thread=true;down_thread=true):        VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):        pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_timeout=3000):        pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;        print_local_addr=false;down_thread=true;up_thread=true)"         propertySeparator="::" />     <defaultCache maxElementsInMemory="10000" eternal="true"        overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"        diskPersistent="false" diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"            properties="replicateAsynchronously=true, replicatePuts=true,                   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>    </defaultCache>     <cache name="velcroCache" maxElementsInMemory="10000" eternal="true"        overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"        diskPersistent="false" diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"            properties="replicateAsynchronously=true, replicatePuts=true,                   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>    </cache>    <cache name="userCache" maxElementsInMemory="10000" eternal="true"        overflowToDisk="true" timeToIdleSeconds="0" timeToLiveSeconds="0"        diskPersistent="false" diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"            properties="replicateAsynchronously=true, replicatePuts=true,                   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>    </cache>    <cache name="resourceCache" maxElementsInMemory="10000"        eternal="true" overflowToDisk="true" timeToIdleSeconds="0"        timeToLiveSeconds="0" diskPersistent="false"        diskExpiryThreadIntervalSeconds="120">        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"            properties="replicateAsynchronously=true, replicatePuts=true,                   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>    </cache></ehcache>
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
EhCache介紹
Encache 緩存介紹
EhCache使用詳細(xì)介紹(轉(zhuǎn))
Hibernate二級(jí)緩存攻略
Hibernate一級(jí)緩存和二級(jí)緩存
ehcache中的timeToLiveSeconds和timeToIdleSeconds時(shí)...
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服