Cache技术―OSCache
Cache技術―OSCache ?
版權聲明:轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明http://aumy2008.blogbus.com/logs/36462938.html
一、簡介
Cache是一種用于提高系統響應速度、改善系統運行性能的技術。尤其是在Web應用中,通過緩存頁面的輸出結果,可以很顯著的改善系統運行性能。
?
OSCache標記庫由OpenSymphony設計,它是一種開創性的緩存方案,它提供了在現有JSP頁面之內實現內存緩存的功能。OSCache是個一個被廣泛采用的高性能的J2EE緩存框架,OSCache還能應用于任何Java應用程序的普通的緩存解決方案。
?
OSCache是當前運用最廣的緩存方案,JBoss,Hibernate,Spring等都對其有支持。
Oscache的使用非常方便,特別是jsp cache用的非常廣泛。Oscache的文檔中也對jsp cache tag的配置有詳細說明。相關內容請參考?OSCache?的?在線文檔??
?
對使用Cache的測試結論:
???????使用cache,隨著循環的增多,用時增長較緩慢,而不使用cache基本是等比例增長。在循環次數較多時,使用cache cpu利用率顯著提高,能達到90%以上。不使用cache則只能上到50%左右,更多是在等待數據庫返回結果。所以使用cache能大大減輕數據庫的壓力,提高應用服務器的利用率,符合我們對應用服務器進行水平擴展的要求。
?
?
二、OSCache的特點和主要特征
(一)、OSCache有以下特點
1、緩存任何對象:你可以不受限制的緩存部分jsp頁面或HTTP請求,任何java對象都可以緩存。
2、擁有全面的API:OSCache API允許你通過編程的方式來控制所有的OSCache特性。
3、永久緩存:緩存能被配置寫入硬盤,因此允許在應用服務器的多次生命周期間緩存創建開銷昂貴的數據。
4、支持集群:集群緩存數據能被單個的進行參數配置,不需要修改代碼。
5、緩存過期:你可以有最大限度的控制緩存對象的過期,包括可插入式的刷新策略(如果默認性能不能滿足需要時)。
(二)、主要特征
1.?????兼容多種支持JSP的web服務器
已經通過兼容測試的web服務器包括OrionServer (1.4.0或者以上版本)、Macromedia JRun (3.0或者以上版本)?、BEA Weblogic (7.x或者以上版本)?、IBM Websphere (5.0版本)、Silverstream (3.7.4版本)、Caucho Resin (1.2.3或者以上版本)、Tomcat (4.0或者以上版本),其他支持servlet2.3、jsp1.2的web服務器應該都是完全兼容OSCache的。
2.?????可選的緩存區
你可以使用內存、硬盤空間、同時使用內存和硬盤或者提供自己的其他資源(需要自己提供適配器)作為緩存區。
使用內存作為緩存區將可以提供更好的性能
使用硬盤作為緩存區可以在服務器重起后迅速恢復緩存內容
同時使用內存和硬盤作為緩存區則可以減少對內存的占用
3.?????靈活的緩存系統
OSCache支持對部分頁面內容或者對頁面級的響應內容進行緩存,編程者可以根據不同的需求、不同的環境選擇不同的緩存級別。
4.?????容錯
在一般的web應用中,如果某個頁面需要和數據庫打交道,而當客戶請求到達時,web應用和數據庫之間無法進行交互,那么將返回給用戶"系統出錯"或者類似的提示信息,如果使用了OSCache的話,你可以使用緩存提供給用戶,給自己贏得維護系統或者采取其他補救的時間。
其它特性還包括對集群的支持、緩存主動刷新等特性,大家可以參考OpenSymphony網站上的其他資源獲取更多的信息。
第二部分:OSCache使用指南
?
一、下載安裝
OSCache是一個基于web應用的組件,他的安裝工作主要是對web應用進行配置,大概的步驟如下:
1.?下載、解壓縮OSCache
從http://www.opensymphony.com/oscache/download.html下載合適的OSCache版本,?解壓縮下載的文件到指定目錄?。
2、新建立一個web應用
3、將OSCache集成到web項目當中。
???????(1)從解壓縮目錄取得oscache.jar?文件放到?/WEB-INF/lib?或相應類庫目錄中,jar文件名可能含有版本號和該版本的發布日期信息等。
???????(2)將oscache.properties、oscache.tld放入WEB-INF\class目錄(確切說是放在項目的src目錄下,編譯的時候會自動生成在WEB-INF\class目錄)。
???????(3)配置項目對應的oscache.properties參數信息。
???????(4)具體使用
??????????????A、緩存對象:直接調用API的接口即可(詳見[Java]用OSCache進行緩存對象)
??????????????B、部分頁面緩存:使用OSCache提供的taglib(修改web.xml文件,在web.xml文件中增加下面的內容,增加對OSCache提供的taglib的支持:<taglib> <taglib-uri>oscache</taglib-uri> <taglib-location>/WEB-INF/classes/ oscache.tld</taglib-location></taglib>或者在jsp頁面使用以下標簽
<%@?taglib?uri="/WEB-INF/classes/oscache.tld"prefix="cache"%>)
??????????????C、整個頁面的緩存:用CashFilter實現頁面級緩存,可緩存單個文件、緩存URL pattern和自己設定緩存屬性的緩存。
<filter> <filter-name>CacheFilter</filter-name> <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> <init-param> <param-name>time</param-name> <param-value>600</param-value> </init-param> <init-param> <param-name>scope</param-name> <param-value>session</param-value> </init-param> </filter> <filter-mapping> <filter-name>CacheFilter</filter-name> <!-對所有jsp頁面內容進行緩存--> <url-pattern>*.jsp</url-pattern> </filter-mapping>[注]?只有客戶訪問時返回http頭信息中代碼為200(也就是訪問已經成功)的頁面信息才能夠被緩存
?
4、配置日志輸出信息。
?
二、oscache.properties?文件配置向導
oscache.properties?中的配置項詳解:
1、cache.memory:
???????是否使用內存緩存; true?或?false。默認為true;?如設置為false,那cache只能緩存到數據庫或硬盤中。
2、cache.capacity
緩存的最大數量。默認是不限制,cache不會移走任何緩存內容。負數被視不限制。
3、cache.algorithm
運算規則。為了使用規則,cache的size必須是指定的。
如果cache的size不指定的話,?將不會限制緩存對象的大小。如果指定了cache的size,但不指定algorithm,那它會默認使用:com.opensymphony.oscache.base.algorithm.LRUCache
有下面三種規則:
*com.opensymphony.oscache.base.algorithm.LRUCache:
last in first out(最后插入的最先調用)。默認選項。
*com.opensymphony.oscache.base.algorithm.FIFOCache:
?first int first out(最先插入的最先調用)。
*com.opensymphony.oscache.base.algorithm.UnlimitedCache :
cache中的內容將永遠不會被丟棄。
如果cache.capacity不指定值的話,它將被設為默認選項。
?
4、cache.blocking
是否同步。true?或者?false。一般設為true,避免讀取臟數據。
5、cache.unlimited.disk
指定硬盤緩存是否要作限制。默認值為false。false的狀況下,disk cache capacity?和cache.capacity的值相同。
6、cache.persistence.class
指定類是被持久化緩存的類。class必須實現PersistenceListener接口。
作為硬盤持久,可以實現com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener接口。
它把class的toString()輸出的hash值作為文件的名稱。如果你要想文件名易讀些(自己設定),DiskPersistenceListener?的父類也能使用,但其可能有非法字符或者過長的名字。
?注意:HashDiskPersistenceListener?和?DiskPersistenceListener?需要設定硬盤路徑:cache.path
7、cache.path
指定硬盤緩存的路徑。目錄如果不存在將被建立。同時注意oscache應該要有權限寫文件系統。
?例:
cache.path=c:\\myapp\\cache
cache.path=/opt/myapp/cache
8、cache.persistence.overflow.only (NEW! Since 2.1)
指定是否只有在內存不足的情況下才使用硬盤緩存。
默認值false。但推薦是true如果內存cache被允許的話。這個屬性徹底的改變了cache的行為,使得persisted cache和memory是完全不同。
9、cache.event.listeners
class名列表(用逗號隔開)。每個class必須實現以下接口中的一個?或者幾個
CacheEntryEventListener:接收cache add/update/flush and remove事件
CacheMapAccessEventListener?:接收cache訪問事件。這個可以讓你跟蹤cache怎么工作。
默認是不配置任何class的。當然你可以使用一下的class:
*com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener :分布式的監聽器。可以廣播到局域網內的其他cache實例。
* com.opensymphony.oscache.extra.CacheEntryEventListenerImpl :一個簡單的監聽器。在cache的生命周期中記錄所有entry的事件。
* com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl :?記錄count of cache map events(cache hits,misses and state hits).
10、cache.key
在application?和?session的作用域時?用于標識cache?對象的,??用于ServletCacheAdministrator;此屬性不是指定為"__oscache_cache"格式時為默認值,如果代碼中需要用到默認值時可以通使用com.opensymphony.oscache.base.Const.DEFAULT_CACHE_KEY?來取得;
11、cache.use.host.domain.in.key
當配置多個服務器時,想通過服備器名稱自動生成cache key時,可將此屬性設為true.?默認值為false;
?
12、Additional Properties
在以上基礎選項之上可以加入一些額外的屬性到此文件中.
例:??JavaGroupsBroadcastingListener?便是額外的.
13、cache.cluster.multicast.ip
用于緩存集群.?默認為231.12.21.132
14、cache.cluster.properties
指集群中的額外配置項.?以下是默認設置:(此屬性的相關說將在集群文檔中說明)
UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
PING(timeout=2000;num_initial_members=3):\
MERGE2(min_interval=5000;max_interval=10000):\
FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
UNICAST(timeout=300,600,1200,2400):\
pbcast.STABLE(desired_avg_gossip=20000):\
FRAG(frag_size=8096;down_thread=false;up_thread=false):\
pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
三、OSCache的基本用法(緩存JSP頁面中部分)
(一):Cache-OSCache提供的緩存標簽
這是OSCache提供的標簽庫中最重要的一個標簽,包括在標簽中的內容將應用緩存機制進行處理,處理的方式將取決于編程者對cache標簽屬性的設置。
第一次請求到達時,標簽中的內容被處理并且緩存起來,當下一個請求到達時,緩存系統會檢查這部分內容的緩存是否已經失效,主要是以下幾項:
1.?緩存時間超過了cache標簽設置的time或者duration屬性規定的超時時間
2. cron屬性規定的時間比緩存信息的開始時間更晚
3.?標簽中緩存的內容在緩存后又被重新刷新過
4.?其他緩存超期設定
如果符合上面四項中的任何一項,被緩存的內容視為已經失效,這時被緩存的內容將被重新處理并且返回處理過后的信息,如果被緩存的內容沒有失效,那么返回給用戶的將是緩存中的信息。
?
cache標簽的屬性說明:
key?-?標識緩存內容的關鍵詞。在指定的作用范圍內必須是唯一的。默認的key是被訪問頁面的URI和后面的請求字符串。
你可以在同一個頁面中使用很多cache標簽而不指定他的key屬性,這種情況下系統使用該頁面的URI和后面的請求字符串,另外再自動給這些key增加一個索引值來區分這些緩存內容。但是不推薦采用這樣的方式。
scope?-?緩存發生作用的范圍,可以是application或者session
time?-?緩存內容的時間段,單位是秒,默認是3600秒,也就是一個小時,如果設定一個負值,那么這部分被緩存的內容將永遠不過期。
duration?-?指定緩存內容失效的時間,是相對time的另一個選擇,可以使用簡單日期格式或者符合USO-8601的日期格式。如:duration=''PT5M'' duration=''5s''等
refresh?- false?或者true。
如果refresh屬性設置為true,不管其他的屬性是否符合條件,這部分被緩存的內容都將被更新,這給編程者一種選擇,決定什么時候必須刷新。
mode?-?如果編程者不希望被緩存的內容增加到給用戶的響應中,可以設置mode屬性為"silent"
其它可用的屬性還包括:cron、groups、language、refreshpolicyclass、refreshpolicyparam。
上面的這些屬性可以單獨使用,也可以根據需要組合使用,下面的例子將講解這些常用屬性的使用方式。
?
(二)?Cache標簽實例分析:
1.?最簡單的cache標簽用法
使用默認的關鍵字來標識cache內容,超時時間是默認的3600秒
<cache:cache>
<% //自己的JSP代碼內容?%>
</cache:cache>
?
2.?用自己指定的字符串標識緩存內容,并且設定作用范圍為session。
<cache:cache key="foobar" scope="session">
<% //自己的JSP代碼內容?%>
</cache:cache>
?
3.動態設定key值,使用自己指定的time屬性設定緩存內容的超時時間,使用動態refresh值決定是否強制內容刷新。
因為OSCache使用key值來標識緩存內容,使用相同的key值將會被認為使用相同的的緩存內容,所以使用動態的key值可以自由的根據不同的角色、不同的要求決定使用不同的緩存內容。
<cache:cache key="<%= product.getId() %>" time="1800" refresh="<%= needRefresh %>">
<% //自己的JSP代碼內容?%>
</cache:cache>
?
4.?設置time屬性為負數使緩存內容永不過期
<cache:cache time="-1">
<% //自己的JSP代碼內容?%>
</cache:cache>
?
5.?使用duration屬性設置超期時間
<cache:cache duration=''PT5M''>
<% //自己的JSP代碼內容?%>
</cache:cache>
?
6.?使用mode屬性使被緩存的內容不加入給客戶的響應中
<cache:cache mode=''silent''>
<% //自己的JSP代碼內容?%>
</cache:cache>
?
四、緩存過濾器?CacheFilter
用CashFilter實現頁面級緩存
在OSCache組件中提供了一個CacheFilter用于實現頁面級的緩存,主要用于對web應用中的某些動態頁面進行緩存,尤其是那些需要生成pdf格式文件/報表、圖片文件等的頁面,不僅減少了數據庫的交互、減少數據庫服務器的壓力,而且對于減少web服務器的性能消耗有很顯著的效果。
這種功能的實現是通過在web.xml中進行配置來決定緩存哪一個或者一組頁面,而且還可以設置緩存的相關屬性,這種基于配置文件的實現方式對于J2EE來說應該是一種標準的實現方式了。
[注]?只有客戶訪問時返回http頭信息中代碼為200(也就是訪問已經成功)的頁面信息才能夠被緩存
?
1.?緩存單個文件
修改web.xml,增加如下內容,確定對/testContent.jsp頁面進行緩存。
<filter> <filter-name>CacheFilter</filter-name>
<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> </filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<!-對/testContent.jsp頁面內容進行緩存-->
<url-pattern>/testContent.jsp</url-pattern>
</filter-mapping>
?
2.?緩存URL pattern
修改web.xml,增加如下內容,確定對*.jsp頁面進行緩存。
<filter> <filter-name>CacheFilter</filter-name>
<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> </filter>
<filter-mapping>
?<filter-name>CacheFilter</filter-name>
<!-對所有jsp頁面內容進行緩存-->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
?
3.?自己設定緩存屬性
在頁面級緩存的情況下,可以通過設置CacheFilter的初始屬性來決定緩存的一些特性:time屬性設置緩存的時間段,默認為3600秒,可以根據自己的需要只有的設置,而scope屬性設置,默認為application,可選項包括application、session
<filter> <filter-name>CacheFilter</filter-name>
<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> <init-param>
<param-name>time</param-name>
<param-value>600</param-value>
</init-param>
<init-param>
<param-name>scope</param-name>
<param-value>session</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<!-對所有jsp頁面內容進行緩存-->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
五、緩存對象
第三部分:Demo
一、對象緩存
1、Cache操作類
import?java.util.Date;
import?com.opensymphony.oscache.base.NeedsRefreshException;
import?com.opensymphony.oscache.general.GeneralCacheAdministrator;
public?class?BaseCache?extends?GeneralCacheAdministrator {????
????private?int?refreshPeriod;?//過期時間(單位為秒);????????
????private?String?keyPrefix;?//關鍵字前綴字符;????????????
????private?static?final?long?serialVersionUID?= -4397192926052141162L;???????
????public?BaseCache(String keyPrefix,int?refreshPeriod){???
????????super();???
????????this.keyPrefix?= keyPrefix;???
????????this.refreshPeriod?= refreshPeriod;???
????}???
????//添加被緩存的對象;???
????public?void?put(String key,Object value){???
????????this.putInCache(this.keyPrefix+"_"+key,value);???
????}???
????//刪除被緩存的對象;???
????public?void?remove(String key){???
????????this.flushEntry(this.keyPrefix+"_"+key);???
????}???
????//刪除所有被緩存的對象;???
????public?void?removeAll(Date date){???
????????this.flushAll(date);???
????}??????????
????public?void?removeAll(){???
????????this.flushAll();???
????}???
????//獲取被緩存的對象;???
????public?Object get(String key)?throws?Exception{???
????????try{???
????????????returnthis.getFromCache(this.keyPrefix+"_"+key,this.refreshPeriod);???
????????}?catch?(NeedsRefreshException e) {???
????????????this.cancelUpdate(this.keyPrefix+"_"+key);???
????????????throw?e;???
????????}?????
????}???????????
}???
?
2、Cache管理類
public?class?CacheManager {???????
????private?BaseCache?newsCache;???????????
????private?static?CacheManager?instance;???
????private?static?Object?lock?=?new?Object();??????????
????private?CacheManager() {???
????????//這個根據配置文件來,初始BaseCache而已;???
????????newsCache?=?new?BaseCache("news",120);????????
????}???????????
????public?static?CacheManager getInstance(){???
????????if?(instance?==?null){???
????????????synchronized(?lock?){???
????????????????if?(instance?==?null){???
????????????????????instance?=?new?CacheManager();???
????????????????}???
????????????}???
????????}???
????????return?instance;???
????}??????
?
????public?void?putUser(User news) {?newsCache.put(news.getId()+"",news);??????}??????
????public?void?removeUser(String newsID) {?newsCache.remove(newsID);???????}??????
????public?User getUser(int?newsID) {???
????????try?{???
????????????return?(User)?newsCache.get(newsID+"");???
????????}?catch?(Exception e) {???
????????????System.out.println("getNews>>newsID["+newsID+"]>>"+e.getMessage());???
????????????User news =?new?User(newsID);???
????????????this.putUser(news);???
????????????return?news;???
????????}???
????}??????
?
?
????public?void?removeAllNews() {???
????????newsCache.removeAll();???
????}??????
}
?
3、對象Bean
public?class?User {
????private?int?id;
????private?String?name;
????private?String?sex;
????private?int?age;
????private?Date?accessTime;?public?User(int?id) {
???????super();
???????this.id?= id;
???????this.accessTime?=?new?Date(System.currentTimeMillis());
????}
????public?String toString() {
???????return?"User info is : id="?+?id?+?"??accessTime="
??????????????+?accessTime.toString();
????}
????public?User(String name, String sex,?int?age) {
???????super();
???????this.name?= name;
???????this.sex?= sex;
???????this.age?= age;
????}
????public?User() {
????}
????public?int?getAge() {
???????return?age;
????}
????public?void?setAge(int?age) {
???????this.age?= age;
????}
????public?String getName() {
???????return?name;
????}
????public?void?setName(String name) {
???????this.name?= name;
????}
????public?String getSex() {
???????return?sex;
????}
????public?void?setSex(String sex) {
???????this.sex?= sex;
????}
????public?int?getId() {
???????return?id;
????}
????public?void?setId(int?id) {
???????this.id?= id;
????}
????public?Date getAccessTime() {
???????return?accessTime;
????}
????public?void?setAccessTime(Date accessTime) {
???????this.accessTime?= accessTime;
????}
}
?
4、測試類
public?class?TestObjectCache {
????public?static?void?main(String[] args) {
???????CacheManager cm=CacheManager.getInstance();
??????
???????TestObjectCache test=new?TestObjectCache();
???????test.print(cm);
????}
???
????public?void?print(CacheManager cm){
???????User user=null;
???????for?(int?i = 0; i < 1000; i++) {
???????????user=cm.getUser(100);
???????????System.out.println("<<"+i+">>: "+user);?????????
???????????if(i==10){
??????????????//刪除緩存id的對象
??????????????cm.removeUser(100+"");
???????????}?????????
???????????if(i==20){
??????????????//刪除所有緩存的對象
??????????????cm.removeAllNews();
???????????}?????????
???????????//?睡眠部分
???????????try?{
??????????????Thread.sleep(30000);
???????????}?catch?(Exception e) {
???????????}
???????}
????}
}
第四部分:小結及其引申
?
緩存是在提升系統響應時常用的一種技術,在系統緩存上通常采用的是有頁面緩存、處理緩存和數據緩存這三種具體的類別,應該說這三種緩存在實現上還是稍有不同,盡管底層的緩存實現是一樣的。
頁面緩存
頁面緩存是指對頁面中的內容片斷進行緩存的方案。比如頁面中有一個部分是顯示欄目中的內容的,那么就可以緩存這個部分,在進行第二次請求的時候就直接從緩存中取出這部分的內容(其實就是這部分的html了),這種情況下,緩存的作用其實非常明顯,在典型的action+service+dao這樣的結構中,在采用頁面緩存后就意味著不需要經過action、service、dao這些層次的處理了,而是直接就返回了,對于系統響應速度的提升來說是非常明顯的。
頁面緩存通常采用oscache來進行實現,oscache提供了一個jsp ?tag,可通過這個tag來包含需要緩存的內容部分,當然,緩存的這個內容部分需要有對服務器的請求或邏輯計算等的,可想而知,去緩存一段靜態html是沒有意義的。
其次需要定義緩存的這段內容的key,例如我們要去緩存頁面中某個欄目的某頁的內容,對于這段內容而言唯一的key就是欄目ID以及當前頁數,這樣就組成了這段緩存的key了,其實這個部分看起來好像是很簡單,但有些時候會很麻煩,要仔細的想清楚這段內容的唯一的標識的key到底是什么,^_^,通常的做法其實可以從action中需要獲取的參數或service接口的參數來決定....
頁 面緩存中還需要做的一個步驟就是通知緩存需要更新,頁面緩存和其他緩存稍有不同,需要告訴它,這個時候不能再使用緩存中的內容了,需要從后臺再重新獲取來 生成新的緩存內容,這個其實很簡單,因為很難在后臺發生變化的時候自己來更新緩存的內容,只能是去通知它,然后讓它再次發起請求來生成新的內容放入緩存 中。
頁面的緩存的使用對于系統的響應速度確實會有很大的提升,在實現頁面緩存時最麻煩的主要是緩存的key的定義以及緩存更新的通知,緩存key的定義這個自然框架是沒法解決的,不過緩存更新的通知其實在框架中可以考慮一種通知模型的,^_^,就像事件通知那樣........在實際的項目中,可以自己去實現一個這樣的通知模型或者就是簡單的采用單例方式來標識某個key是否需要更新。
頁面緩存在實際的項目中使用非常的多。
處理緩存
處理緩存是指對于action、service、dao或者系統層次中的某方法進行緩存,說直接點,就是對某個類的某個方法的結果做緩存,這樣在下次進行完全相同的請求的時候就可以直接取緩存了,這種響應速度的提升也是非常明顯的。
處理緩存在現在的情況下其實采用任務的緩存工具包都可以實現,如oscache、ehcache、jbosscache等,但目前還沒有處理緩存框架的出現,這個和處理緩存是否應該存在的意義也是有關系的,處理緩存框架要做到的其實就像攔截一樣的方式,和oscache ?tag類似。
同樣,處理緩存的麻煩也在于怎么樣去定義這個key,很多情況下可以根據方法的輸入作為key,方法的輸出作為key的值,但也會有其他一些復雜的情況,這個時候定義key就會變得復雜些了。
處理緩存同樣有通知更新緩存的情況,和頁面緩存基本是一樣的。
應該說,處理緩存和頁面緩存非常的相似,從實現上來說基本是完全一致的,在使用上來講處理緩存使用的好像不多。
數據緩存
數據緩存估計大家都很熟悉,就是對系統的數據進行緩存的方式,典型的就是Hibernate的一級、二級數據緩存。
數據緩存在實現上如果是用hibernate的話更多的是直接使用hibernate的一級、二級以及查詢緩存,如果自己要實現的話可以去參考hibernate的實現機制。
數據緩存的key在一級、二級緩存中采用的都是數據的標識鍵的值的方式,查詢緩存采用的是查詢參數、查詢語句的方式。
數據緩存的更新則是hibernate在進行存儲時直接更新緩存的內容,而對于查詢緩存則是采用全部直接清除的方式,這樣在下次進行查詢時自然會重新去查詢,^_^,大家可能會想,為什么頁面緩存和處理緩存不采用這樣的方式來實現緩存的更新,稍微想想就知道了,在后臺發生改變的時候其實是不知道需要移除哪些key的,所以hibernate為了避免這個麻煩,采用的就是當數據一旦發生改變的時候就清除全部的查詢緩存,而不是只去清除相關的緩存,其實這里可以采用一種訂閱式的模型,呵呵,當然,也增加了框架的復雜度。
數據緩存使用的應該是最多的,效果也是很明顯的。
以上三種緩存是目前緩存實現時通常碰到的三種狀況,里面按使用的多少來排序應該是:數據緩存、頁面緩存和處理緩存;實現的難度上從難到易的順序應該是:處理緩存、頁面緩存、數據緩存;對于系統響應速度提升的效果來說從最好到好的順序應該是:頁面緩存、處理緩存、數據緩存。
?
?
補充部分:
???????在SSH項目應用中,可以以對象的形式來緩存展現給用戶的數據信息。對象的緩存要充分利用分組帶來的好處(可以分組刪除被緩存的對象),這樣在執行數據庫的CUD操作時,可以調用刪除相應組別的緩存對象。
示例代碼:
????private?CacheManager?cm;
???
????private?final?static?String?CACHE_KEY_SUB="RetJobs";
?
????public?JobAction() {
???????//獲取緩存管理對象
???????cm?= CacheManager.getInstance();
????}
?????????
查詢部分
???????page=(Page<RetJob>)(cm.get(CACHE_KEY_SUB+"_"+currentPage));
???????if(page==null){
???????????//--------------------需要緩存對象部分-----------------------
???????????page?=?retJobBaseModel.getJobs(currentPage,?pageSize,statusCondition);
???????????//-------------------------------------------
???????????//緩存對象(含所屬分組信息)
???????????cm.put(page,?CACHE_KEY_SUB+"_"+currentPage,new?String[]{CACHE_KEY_SUB});
???????}
?
CUD操作部分
setCacheDisabled(CACHE_KEY_SUB);
?
????private?void?setCacheDisabled(String?group) {
???????//通過組別信息來刪除緩存的對象。
???????cm.removeObjectByGroup(group);
????}
CacheManager?類
public?class?CacheManager {
????private?BaseCache?newsCache;
????private?static?CacheManager?instance;
????private?static?Object?lock?=?new?Object();
?
????private?CacheManager() {
???????//?這個根據配置文件來,初始BaseCache而已;
???????newsCache?=?new?BaseCache("hrms", 300);
????}
?
????public?static?CacheManager getInstance() {
???????if?(instance?==?null) {
???????????synchronized?(lock) {
??????????????if?(instance?==?null) {
??????????????????instance?=?new?CacheManager();
??????????????}
???????????}
???????}
???????return?instance;
????}
?
????public?void?put(Object news,String key,String[] groups) {
???????newsCache.put(key, news,groups);
????}
????public?void?remove(String key) {
???????newsCache.remove(key);
????}
????public?Object get(String key) {
???????try?{
???????????return?newsCache.get(key);
???????}?catch?(Exception e) {
???????????return?null;
???????}
????}
????public?void?removeAll() {
???????newsCache.removeAll();
????}??
????public?void?removeObjectByGroup(String group){
???????newsCache.removeObjectByGroup(group);
????}
}
BaseCache?類增加的2個方法如下:
????//?添加被緩存的對象;
????public?void?put(String key, Object value,String[] groups) {
???????this.putInCache(this.keyPrefix?+?"_"?+ key, value,groups);
????}
????//刪除該組的緩存對象
????public?void?removeObjectByGroup(String group){
???????this.flushGroup(group);
????}
轉載于:https://www.cnblogs.com/-lpf/p/4312642.html
總結
以上是生活随笔為你收集整理的Cache技术―OSCache的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: (转) 基于MapReduce的Item
- 下一篇: 持续集成:CruiseControl.N
