Ehcache中儲存緩存的方式
目錄
1 堆內存(MemoryStore)
1.1 指定可用內存
1.2 驅除策略
1.3 元素過期
2 非堆內存(BigMemory)
3 磁盤(DiskStore)
3.1 指定可用容量
3.2 元素過期
在Ehcache中對於緩存的存儲主要有三種方式:分別是堆內存、非堆內存和磁盤。其中非堆內存是針對於企業版Ehcache才有的功能,它可以不受Java GC的影響,能夠創建很大的緩存。
1 堆內存(MemoryStore)
我們通常所有的MemoryStore實際上就是堆內存存儲。MemoryStore總是可用的,所有的元素都可以儲存在MemoryStore中。MemoryStore是線程安全的,相比另外兩種儲存方式而言其訪問速度也是最快的。通常我們在往緩存里面添加元素的時候,其首先就是存放在MemoryStore里面的,但是我們又不能說連續不斷的往MemoryStore里面存放元素,這就涉及到到底能放多少元素的問題。
1.1 指定可用內存
Ehcache規定我們在使用一個Cache時必須在CacheManager級別指定可用的內存大小或者是在Cache級別指定可用的內存大小或所允許存放的元素的最大數量。在CacheManager級別指定的內存大小是其內部所有Cache一起所能使用的內存的最大量。CacheManager級別指定內存大小是通過maxBytesLocalHeap來指定的,如:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" maxBytesLocalHeap="500M"> </ehcache>
1.上面指定了我們的CacheManager所能使用的最大內存是500M。
2.CacheManager級別指定了內存大小后我們在Cache上也可以指定其能使用的最大內存,但不能指定其所能存儲元素的最大數量。
另外,如果我們的CacheManager沒有指定可用的內存大小,我們可以通過maxBytesLocalHeap在Cache級別指定可用的內存大小,或者通過maxEntriesLocalHeap在Cache級別指定允許儲存元素的最大數量,但是maxEntriesLocalHeap和maxBytesLocalHeap不能同時使用。如下在CacheManager級別使用maxBytesLocalHeap,然而在Cache級別使用maxEntriesLocalHeap是不行的。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" maxBytesLocalHeap="500M"> <cache name="ttt" maxEntriesLocalHeap="10000"/> </ehcache>
如下在Cache級別同時使用maxBytesLocalHeap和maxEntriesLocalHeap也是不行的。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> <cache name="ttt" maxBytesLocalHeap="50M" maxEntriesLocalHeap="10000"/> </ehcache>
1.2 驅除策略
那么當我們內存中的元素大小或者數量超過了預設的大小之后怎么辦呢?這個時候如果我們設置了允許溢出,如overflowToDisk或overflowToOffHeap,則會把某些元素溢出到對應的儲存器中。如果不允許溢出,則會先刪除原有的某些元素。至於是哪個元素溢出、哪個元素刪除則在不存在超時的情況下與我們的內存驅除策略有關,
這是通過Cache的memoryStoreEvictionPolicy屬性來指定的。其可選值有LRU、LFU和FIFO,默認是LRU。但是如果有過期元素存在的話則會優先驅除已經過期的元素,然后再考慮驅除策略memoryStoreEvictionPolicy。
LRU(Least Recently Used):最近最少使用。當我們把一個元素儲存到Cache中或者從Cache中取出時都會更新該元素的最后使用時間。當采用最近最少使用原則進行驅除時會優先把最后使用時間最早的元素進行驅除。
LFU(Least Frequently Used):最不常使用的。每次我們從Cache中獲取一個元素時都會更新該元素的hitCount屬性值加1。當采用最不常使用原則進行驅除時hitCount屬性值最小的元素將優先驅除。
FIFO(First In First Out):先進先出。當采用這種驅除原則時將優先驅除最先儲存的元素。
1.3 元素過期
在上文中我們已經知道在不存在元素過期的情況下,驅除哪個元素是與我們的內存驅除策略有關的。但如果存在過期元素的話則會優先驅除已經過期的元素。關於控制元素是否過期我們可以通過cache的幾個屬性來定義。
timeToIdleSeconds:單位是秒,表示一個元素在不被請求的情況下允許在緩存中存在的最長時間。默認值是0,表示不限制。
timeToLiveSeconds:單位是秒,表示一個元素不管有沒有被使用,其在緩存中允許存在的最長時間。默認是0,表示不限制。一般timeToLiveSeconds要比timeToIdleSeconds長,否則就timeToIdleSeconds就失去意義了。
eternal:boolean類型,表示是否永恆,默認為false。當設為true時,表示緩存中的元素永遠不會過期,timeToIdleSeconds和timeToLiveSeconds就失去作用了。這個時候元素就只能由驅除策略來進行驅除了。
當我們的元素過期以后,為了保持Cache的性能,Ehcache不一定馬上就會將過期的元素刪除或者驅除到其它存儲容器中,它可能還在原來的位置。之所以說不一定是因為有可能當一個元素過期時恰好Cache需要刪除元素或者驅除元素到其它存儲容器中,這個時候我們的過期元素將優先被刪除或者驅除。另外,當我們在請求一個元素的時候,如果Ehcache發現該元素已經過期的話也會立刻將該元素刪除。
<cache name="ttt" maxBytesLocalHeap="50M" timeToIdleSeconds="600" timeToLiveSeconds="3600" memoryStoreEvictionPolicy="LFU" />
在上面的配置中,我們指定了該Cache允許元素不被請求的時間是10分鍾,最大存活時間是1小時,使用的驅除策略是LFU(最不常使用)。
2 非堆內存(BigMemory)
非堆內存存儲是針對於企業版才有的功能,它可以不受Java GC的影響,能夠創建很大的緩存。BigMemory保存的都是一個個的字節,在保存元素的時候Ehcache會對元素進行序列化再保存到BigMemory中,然后在讀取的時候又會把讀取到的字節進行反序列化。所以存放在其中的元素的key和value都必須是能夠序列化的。
3 磁盤(DiskStore)
磁盤存儲可以存儲內存中驅除過來的元素,也可以在系統重啟的時候將內存中的緩存信息保存起來,供系統重新啟動后使用。磁盤存儲是非必須的,但是使用DiskStore的時候我們需要指定一個磁盤目錄來存放緩存信息。這可以在ehcache.xml文件中的ehcahce元素下的定義一個diskStore元素並指定其path屬性。由diskStore元素是定義在ehcache元素下我們看出diskStore在CacheManager范圍內是共享的,其是線程安全的。如果我們沒有定義diskStore元素時,DiskStore會使用默認的目錄作為其存儲目錄,該目錄就是java.io.tmpdir,即Java的臨時目錄。當然我們也可以指定一個絕對路徑。
當我們指定diskStore元素的path為以下值時會被替換為實際對應的目錄:
l user.home:用戶的家目錄。
l user.dir:用戶的當前工作目錄。
l java.io.tmpdir:Java臨時目錄。
l 在命令行指定的屬性,如“java -Dehcache.disk.store.dir=D:\\abc …..”。
子目錄的話可以這樣指定:user.home/ehcache。
此外需要注意的是因為DiskStore是把信息存放在磁盤上的,所以我們存放在磁盤上的元素必須是可以序列化的。CacheManager的DiskStore路徑一旦設置好了之后將不能再更改。如果硬是更改了,那么我們的CacheManager需要基於新的路徑重新建立。
3.1 指定可用容量
指定可用容量的時候我們可以在CacheManager級別通過maxBytesLocalDisk來指定。而在Cache級別我們可以通過maxBytesLocalDisk和maxEntriesLocalDisk來指定。因為DiskStore是可選的,所以這些屬性也都是可選的。另外不像MemoryStore那樣,我們在Cache級別上可以同時指定maxBytesLocalDisk和maxEntriesLocalDisk。如:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" maxBytesLocalDisk="50G"> <diskStore path="d:\\ehcache"/> <cache name="ttt" maxBytesLocalHeap="100M" maxBytesLocalDisk="50G" maxEntriesLocalDisk="10000"/> </ehcache>
DiskStore中驅除元素跟MemoryStore中驅除元素的規則是不一樣的。當往DiskStore中添加元素且此時DiskStore中的容量已經超出限制時將采用LFU(最不常用)驅除規則將對應的元素進行刪除,而且該驅除規則是不可配置的。
3.2 元素過期
DiskStore中的元素過期跟MemoryStore中的元素過期是同樣定義的。對於每一個Cache而言都擁有一個線程用於檢查並移除其中的過期元素。至於多久檢查一次,我們可以通過cache元素的diskExpiryThreadIntervalSeconds 屬性來指定,默認是每兩分鍾檢查一次。
(注:本文是基於Ehcache2.8.1所寫。)