天天看點

EHCache 緩存 定位

EHCache 是一個純java的在程序中的緩存,它具有以下特性:快速,簡單,為Hibernate2.1充當可插入的緩存,最小的依賴性,全面的文檔和測試.官方網站

毫無疑問,幾乎所有的網站的首頁都是通路率最高的,而首頁上的資料來源又是非常廣泛的,大多數來自不同的對象,而且有可能來自不同的db ,是以給首頁做緩存是一個不錯的主意,那麼首頁的緩存政策是什麼樣子的呢,我認為應該是某個固定時間之内不變的,比如說2 分鐘更新一次.那麼這個緩存應該做在什麼地方呢,讓我們來看一下,假設您的應用的結構是page-filter-action-service-dao-db ,這個過程中的- 的地方都是可以做緩存的地方,根據頁面緩存的特征,應該把頁面緩存做到盡量靠近客戶的地方,就是在page 和filter 之間,這樣的優點就是第一個使用者請求之後,頁面被緩存,第二個使用者再來請求的時候,走到filter 這個請求就結束了,無需再走後面的action-service-dao-db .帶來的好處是伺服器壓力的減低和客戶段頁面響應速度的加快.

那麼我們來看一下如何使用ehcache 做到這一點.

在使用ehcache 的頁面緩存之前,我們必須要了解ehcache 的幾個概念,

1 timeToIdleSeconds ,多長時間不通路該緩存,那麼ehcache 就會清除該緩存.

2 timeToLiveSeconds ,緩存的存活時間,從開始建立的時間算起.

首頁的頁面緩存的存活時間,我們定的是2 分鐘,timeToLiveSeconds 應該設定為120 ,同時我們的timeToIdleSeconds 最好也設定為2 分鐘,或者小于2 分鐘.我們來看一下下面這個配置,這個配置片段應該放到ehcache.xml 中:

<cache name= "SimplePageCachingFilter"

maxElementsInMemory = "10"

maxElementsOnDisk = "10"

eternal = "false"

overflowToDisk = "true"

diskSpoolBufferSizeMB = "20"

timeToIdleSeconds = "10"

timeToLiveSeconds = "10"

memoryStoreEvictionPolicy = "LFU"

/>

SimplePageCachingFilter 是緩存的名字,maxElementsInMemory 表示記憶體中SimplePageCachingFilter 緩存中元素的最大數量為10 ,maxElementsOnDisk 是指持久化該緩存的元素到硬碟上的最大數量也為10 ,eternal=false 意味着該緩存會死亡.overflowToDisk=true 意思是表示當緩存中元素的數量超過限制時,就把這些元素持久化到硬碟,如果overflowToDisk 是false ,那麼maxElementsOnDisk 的設定就沒有什麼意義了.memoryStoreEvictionPolicy=LFU 是指按照緩存的hit 值來清除,也就是說緩存滿了之後,新的對象需要緩存時,将會将緩存中hit 值最小的對象清除出緩存,給新的對象騰出地方來了(文章最後有ehcache 中自帶的3 種緩存清空政策的介紹).

SimplePageCachingFilter 的配置,

<filter>

<filter-name> indexCacheFilter </filter-name>

<filter-class>

net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter

</filter-class>

</filter>

<filter-mapping>

<url-pattern> *index.action </url-pattern>

</filter-mapping>

就隻需要這麼多步驟,我們就可以給某個頁面做一個緩存的,把上面這段配置放到你的web.xml 中,那麼當你打開首頁的時候,你會發現,2 分鐘才會有一堆sql 語句出現在控制台上.當然你也可以調成5 分鐘,總之一切都在控制中.

好了,緩存整個頁面看上去是非常的簡單,甚至都不需要寫一行代碼,隻需要幾行配置就行了,夠簡單吧,雖然看上去簡單,但是事實上内部實作卻不簡單哦,有興趣的話,大家可以看看SimplePageCachingFilter 繼承體系的源代碼.

上面的配置針對的情況是緩存首頁的全部,如果你隻想緩存首頁的部分内容時,你需要使用SimplePageFragmentCachingFilter 這個filter .我們看一下如下片斷:

net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter

<filter-name> indexCacheFilter filter-name>

<url-pattern> */index_right.jsp </url-pattern>

</filter-mapping >

這個jsp 需要被jsp:include 到其他頁面,這樣就做到的局部頁面的緩存.這一點貌似沒有oscache 的tag 好用.

事實上在cachefilter 中還有一個特性,就是gzip ,也就是說緩存中的元素是被壓縮過的,如果客戶浏覽器支援壓縮的話,filter 會直接傳回壓縮過的流,這樣節省了帶寬,把解壓的工作交給了客戶浏覽器,如果客戶的浏覽器不支援gzip ,那麼filter 會把緩存的元素拿出來解壓後再傳回給客戶浏覽器(大多數爬蟲是不支援gzip 的,是以filter 也會解壓後再傳回流),這樣做的優點是節省帶寬,缺點就是增加了客戶浏覽器的負擔(但是我覺得對當代的計算機而言,這個負擔微乎其微).

好了,如果你的頁面正好也需要用到頁面緩存,不防可以考慮一下ehcache ,因為它實在是非常簡單,而且易用.

總結:ehcache 是一個非常輕量級的緩存實作,而且從1.2 之後就支援了叢集,目前的最新版本是1.3 ,而且是hibernate 預設的緩存provider .雖然本文是介紹的是ehcache 對頁面緩存的支援,但是ehcache 的功能遠不止如此,當然要使用好緩存,對JEE 中緩存的原理,使用範圍,适用場景等等都需要有比較深刻的了解,這樣才能用好緩存,用對緩存.

ehcache 中緩存的3 種清空政策:

1 FIFO ,first in first out ,這個是大家最熟的,先進先出,不多講了

2 LFU , Less Frequently Used ,就是上面例子中使用的政策,直白一點就是講一直以來最少被使用的.如上面所講,緩存的元素有一個hit 屬性,hit 值最小的将會被清出緩存.

2 LRU ,Least Recently Used ,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離目前時間最遠的元素将被清出緩存. 

簡介

Ehcache倆中緩存機制:

? MemoryStore(記憶體存儲)

? DiskStore(磁盤存儲)

MemoryStore

MemoryStore總是可用的,但不可直接操作,當中存儲着所有的Cache.

? 合适的Element類型

所有的Element都可以放在MemoryStore中.

? 安全性:使用多個線程并行檢查記憶體洩露.

? JDK:使用了JDK1.5的LinkedHashMap來存放Elemen.t

? 快速的:是最快的緩存機制,因為它是存放在記憶體中.

? 失效政策(Memory)

Cache 可以配置最大緩存Element的個數,以及失效時間.如果在添加Elemtent時,緩存中的Element個數達到了最大緩存數并且 overflowToDisk配置的屬性為true,Ehcache會更具配置項MemoryStoreEvictionPolicy的失效政策将 Element輸出到磁盤.如果overflowToDisk為fasle,Ehcache将删除記憶體中Element.Ehcache支援三種失效政策:LRU,LFU,FIFO.

值得注意的是緩存中失效的Element并不會别馬上清理掉,是以想得到記憶體的真實大小應該調用方法calculateInMemorySize()方法.

DiskStore

DiskStore可緩存到外部裝置上(硬碟).

? DiskStores are Optional

Ehcache從1.5版本開始支援DiskStore.如果你需要多個DiskStore的話,最好給他們配置不同的檔案路徑.

? 關閉磁盤緩存:隻要注釋掉ehcache.xml配置檔案中的磁盤緩存配置項即可.而ehcache-failsafe.xml的磁盤緩存配置不會影響到你自己的cache.

這裡要注意要想使用磁盤緩存,緩存的Element必須實作序列化接口.否則會抛出NotSerializableException異常.

? 存儲:Ehcache會将每個緩存配置的檔案路徑下建立一個cache_name.data檔案,如果使用的磁盤持久化技術,還會生成一個cache name.index檔案.

? 失效

Ehcache有一個背景線程專門做Ellment失效監測以及清除工作.設定線程運作間隔時間,可通過設定diskExpiryThreadIntervalSeconds屬性來完成,此值不宜設定過低,否則會導緻清理線程占用大量CPU資源.預設值是120秒.

? 持久化

持久化可在Element的diskPersistent配置項中配置,如果配置為"false"或是"omitted"在CacheManager shutdown或是startup後,用來緩存Element的檔案将被清除掉.如果設定為"true",data和index檔案會被儲存下來,對于新建立的CacheManager Element也是可用的.

使用時必須顯示調用cache. Flush()才會将資料緩存到磁盤中.

磁盤緩存步驟:從MemoryStore中把沒有失效的Element重新整理到DiskStore,Element被寫入到data檔案,Element将被序列化到index檔案.

Ehcache緩存回收政策

緩存回收就是當緩存滿了的時候,Ehcache會根據指定的政策來清理緩存.這裡的緩存回收政策有别與Ehcache中的失效清理政策.失效清理政策是對失效的Element進行批量清理時所采用的政策,最終所有失效的Element都将被清理,隻不過是清理的先後順序不同罷了.Ehcache中緩存的最大 Element數是由maxElementsInMemory來指定的.當緩存中的Element個數達到maxElementsInMemory指定的值時,Ehcache會根據具體的政策來清理緩存,預設的政策是LRU(最近最少使用).

磁盤緩存大小預設是沒有限制的,不過可通過maxElementsOnDisk來指定.當磁盤緩存達到maxElementsOnDisk指定的值時,Ehcache會清理磁盤中的緩存使用預設政策是LFU(使用頻率最低).

Make sure you are using a supported Java version. 

Place the Ehcache jar into your classpath. 

Ensure that any libraries required to satisfy dependencies are also in the classpath. 

Configure ehcache.xml and place it in your classpath. 

Optionally, configure an appropriate logging level.

Downloads: http://sourceforge.net/projects/ehcache/files/

Welcome to ehcache: