SpringAOP+Encache緩存技術

        是否常常在爲數據查詢較慢而發愁,當你需要查詢數據巨量較大而更改較少的數據時,不妨使用緩存技術,他會帶給你更加效率的查詢。今天,和大家分享一下利用Spring管理Encache來實現數據的緩存。

        Ehcache是一個純Java的進程內緩存框架,它支持read-only和read/write緩存,內存和磁盤緩存。使用過hibernate的童鞋應該都清楚,hibernate的二級緩存就可以採用ehcache來實現。這裏就不過多講解ehcache的原理,它的底層實際是一個Map,以key-value的形式保存緩存數據,下面對ehcache.xml做一下介紹。

圖片1.png

 

在上面的配置文件中,配置了兩個cache,一個是默認的缺省的緩存策略,一個是自定義的methodCache,其中各個屬性的作用分別如下:

diskStore中的path:設置緩存文件的創建位置,比如:user.home(用戶主目錄),user.dir (用戶當前工作目錄),java.io.tmpdir(系統默認臨時文件路徑),以及自定義的存儲位置(如:D:\cache\onlinestudy);

name: Cache的唯一標識;

maxElementsInMemory: 內存中最大緩存對象數;

maxElementsOnDisk: 磁盤中最大緩存對象數, 若是0表示無窮大;

eternal: Element是否永久有效, 一但設置了, timeout 將不起作用;

overflowToDisk: 當內存中 Element 數量達到 maxElementsInMemory , Ehcache 是否將 Element 寫到磁盤中;

timeToLiveSeconds:設置Element 在失效前允許存活時間. 最大時間介於創建時間和失效時間之間.僅當 Element 不是永久有效時使用, 默認爲 0 : 表示存活時間無窮大;

diskPersistent:是否緩存虛擬機重啓期數據;

diskExpiryThreadIntervalSeconds: 磁盤失效線程運行時間間隔, 默認是120秒;

diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存) 的緩存區大小, 默認30MB

memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時, Ehcache將會根據指定的策略去清理內存.默認策略是LRU(最近最少使用). 可以設置爲 FIFO(先進先出) LFU(較少使用)

對應上面參數的具體設置,就需要根據項目的實際情況而定,綜合考慮程序的響應時間、內存佔用空間等效率因素。

三、查詢緩存的實現

在程序的允許範圍內使用查詢緩存,能在一定程度上提高程序的性能,提高訪問速度,降低服務器的壓力。哪些地方我們需要使用查詢緩存呢,一些經常被訪問且變動性小的數據建議使用查詢緩存,比如:系統的菜單,經常被訪問的統計數據等。

通過上面的準備,就可以實現查詢緩存了。查詢緩存分爲兩部分,一是緩存的寫入/更新,二是緩存的讀取。緩存通過ehcache來實現,而對他的操作就通過Spring AOP來控制。

比如給OPM項目(spring3+struts2+spring JdbcTemplate)增加查詢緩存的功能,具體步驟如下:

1.需要給項目增加ehcache相關的jar包和ehcache.xml配置文件,這裏我們就採用上面給出的ehcache.xml中的methodCache作爲這次的查詢緩存;

2.用spring管理ehcache,在applicationContext.xml中增加如下配置。

圖片2.png

3.切面編程(AOP)的聲明,本次使用AOP註解的方式來實現,因此需要在applicationContext.xml中聲明,並且還需要指定spring自動掃描註冊的包類配置項如下。

圖片3.png

4. 編寫aspect類,該QueryCache類中主要有兩個功能方法,一個用於查詢緩存,一個用於清除緩存,代碼如下。

圖片4.png

圖片5.png

  上面的第一個advice方法queryCache就是對com.travelsky.ccboy.dao包及其子包中類的以query或find開頭的方法進行環繞通知,首先程序在調用目標查詢方法之前,先去cache中查找是否有對應的查詢結果,如果有則直接放回結果,如果沒有就去調用目標方法,然後將查詢的結果保存到緩存中,再返回結果,就避免了每次都去數據庫中查找,則樣就提高了查詢的速度。
  這裏有一個關鍵的問題就是怎麼來構造cache的key,這裏使用了目標方法的完整類路徑+方法名+查詢參數值作爲key,這就保證了對同一個方法使用不同的參數查詢可以有不同的緩存;還需要注意的問題有:(1)如果目標查詢方法的參數是一個引用對象,比如queryPersonPO,則我們需要重寫QueryPersonPO類的equals方法,以保證創建key的有效性;(2)由於ehcache的緩存使用了內存/磁盤緩存,所以我們需要對被緩存的對象類(也就是目標查詢方法返回的對象)進行序列化,以保證能正確的緩存和讀取;(3)在方法的上面考慮使用了synchronized,目的是避免多人在同一時刻訪問時重複的查詢數據庫,確保一次查詢成功,多人共享數據的目的。
  緩存的清除出了通過配置的ehcache.xml中的規則管理之外,上面還提供了一個清除緩存的clean方法,使用了After return advice,原理是隻要調用了以update或delete開頭的方法,這就把這個類的緩存都清除,下次調用查詢方法時再進行緩存。
  下面是測試運行結果。

圖片6.png

從上圖可以看出,兩個線程同時使用相同的參數訪問了同一個方法兩次,而實際訪問數據庫只有一次,當第一次訪問成功後,後面訪問的時間就大大減少了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章