簡單的使用ehcache


之前一直感覺緩存是高上大的東西,沒有心思去研究。做了之后發現,簡單的使用還是很容易的。這里記錄ehcache在jfinal中的簡單使用。

1.ehcahe簡介

EhCache 是一個純Java的進程內緩存框架,具有快速、精干等特點,是Hibernate中默認的CacheProvider。

看到官網上已經3.0了。

2.作用

我把它當做一個可以存儲數據和讀取數據的存在。緩存其實就一個key-value的數據存儲工具。目前我使用過兩個方面。

一是緩存數據庫的數據。

都說連接數據庫的開銷很大,所以對數據變化較小的一部分可以緩存起來,下次直接從緩存中取數據。(關於數據的安全性未曾考慮)。

二是存儲變量。

在web后端開發過程中,有些數據需要保存起來方便下次使用。比如短信的驗證碼。我之前都是在類中添加一個map類變量,然后存入map,下次取出或者銷毀。這樣做事可以的,類實例化后。類變量就加載到內存中了,可以存儲數據。但有個問題,關於類的創建和銷毀的聲明周期問題。不能確保他什么時候去銷毀。或者說,這一塊我了解有限,還沒研究到。

因此,放到緩存中就可以了。緩存可以設置數據的大小,失效時間。

3.用到的兩個基本實現

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:noNamespaceSchemaLocation="ehcache.xsd"
 4          updateCheck="false" monitoring="autodetect"
 5          dynamicConfig="true">
 6          
 7     <diskStore path="java.io.tmpdir"/>
 8     
 9     <defaultCache
10            maxEntriesLocalHeap="10000"
11            eternal="false"
12            overflowToDisk="true"
13            timeToIdleSeconds="20"
14            timeToLiveSeconds="60">
15     </defaultCache>
16 
17      <!-- 內存中最多可以緩存1000個element,超出1000的,不輸出到磁盤中。緩存是永久有效的 
18          name:cache唯一標識
19          maxElementsInMemory:內存中最大緩存對象數
20          eternal:Element是否永久有效,一但設置了,timeout將不起作用。
21          verflowToDisk:配置此屬性,當內存中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁盤中。
22          memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。
23                                      默認策略是LRU(最近最少使用)。還可以設置為FIFO(先進先出)或是LFU(較少使用)。 
24      -->        
25     <cache name="zone"
26        maxElementsInMemory="1000"
27        eternal="true"
28        overflowToDisk="false"
29        memoryStoreEvictionPolicy="LRU"
30      />
31         
32     <!--
33         內存中最多可緩存10000個Element,其中的element會在閑置5分鍾或是存活10分鍾之后失效。
34     If there are more than 10000 elements it will overflow to the
35     disk cache, which in this configuration will go to wherever java.io.tmp is
36     defined on your system. On a standard Linux system this will be /tmp"
37     diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每個Cache都應該有自己的一個緩沖區。
38     timeToIdleSeconds:設置對象在失效前的允許閑置時間(單位:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大。 
39     timeToLiveSeconds:設置對象在失效前允許存活時間(單位:秒)。最大時間介於創建時間和失效時間之間。僅當eternal=false對象不是永久有效時使用,默認是0.,也就是對象存活時間無窮大。 
40     transactionalMode="off" 使ehcache作為JTA事務的參與者
maxEntriesLocalHeap:堆內存中最大緩存對象數,0沒有限制
Sets the maximum number of objects that will be held on heap memory.  0 = no limit.
maxEntriesLocalDisk:磁盤中的最大對象數,默認為0不限制
Sets the maximum number of objects that will be maintained in the DiskStore
The default value is zero, meaning unlimited.
41 --> 42 <cache name="mobileMsg" 43 maxEntriesLocalHeap="10000" 44 maxEntriesLocalDisk="1000" 45 eternal="false" 46 overflowToDisk="true" 47 diskSpoolBufferSizeMB="20" 48 timeToIdleSeconds="300" 49 timeToLiveSeconds="600" 50 memoryStoreEvictionPolicy="LFU" 51 transactionalMode="off" 52 /> 53 54 </ehcache>

3.1追加使用的問題:

  • 從cache取出的對象默認會

    copyOnRead="false"
    copyOnWrite="false".如果對取出的對象操作,就會修改cache中的對象。因為序列化問題。因此,如果想要對緩存的數據修改而不改變緩存中的原始數據,應該將這兩個設為true。

4.在jfinal中的使用

jfinal框架集成了ehcache,只要簡單配置就可以使用了。配置如下:

4.1在commonconfig中添加插件:

1 @Override
2     public void configPlugin(Plugins me) {
3         me.add(new EhCachePlugin());
4 }

4.2.通過CacheKit管理緩存

上面的配置可以看出,一個緩存(姑且這么叫)由一個name字段唯一標識,數據又是key-value,因此,只有name-key就可以唯一標識value.

4.2.1將變量加入緩存:

1 CacheKit.put(cacheName, key, value);
  • cacheName:在xml中配置的緩存name字段
  • key:唯一標識
  • value:你要存儲的對象,value可以是任何對象、數據類型,比如person,map,list等

4.2.2取出

1 CacheKit.get(cacheName, key);

4.3findByCache中使用

這個直接使用就是加入緩存了。

1 Db.findByCache(cacheName, key, sql);

 

 

ehcache基本原理

  (2014-12-29 11:03:33)
 

ehcache是一個用Java實現的使用簡單,高速,實現線程安全的緩存管理類庫,ehcache提供了用內存,磁盤文件存儲,以及分布式存儲方式等多種靈活的cache管理方案。同時ehcache作為開放源代碼項目,采用限制比較寬松的Apache License V2.0作為授權方式,被廣泛地用於Hibernate,  Spring,Cocoon等其他開源系統

Ehcache的類層次模型主要為三層,最上層的是CacheManager,他是操作Ehcache的入口。我們可以通過CacheManager.getInstance()獲得一個單個的CacheManager,或者通過CacheManager的構造函數創建一個新的CacheManager。每個CacheManager都管理着多個Cache。而每個Cache都以一種類Hash的方式,關聯着多個Elemenat。而Element則是我們用於存放要緩存內容的地方。

ehcache的刷新策略
ehcache的刷新策略是當緩存在放入的時候記錄一個放入時間,它是用Lazy Evict的方式,在取的時候同設置的TTL比較

ehcache緩存的3種清空策略:
1 FIFO,先進先出
2 LFU,最少被使用,緩存的元素有一個hit屬性,hit值最小的將會被清出緩存。
3 LRU,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那么現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。

事件處理
可以為CacheManager添加事件監聽,當對CacheManager增刪Cache時,事件處理器將會得到通知。要配置事件處理,需要通過ehcache的配置文件來完成。
可以為Cache添加事件監聽,當對Cache增刪Element時,事件處理器將會得到通知。要配置事件處理,需要通過ehcache的配置文件來完成。

ehcache參數配置:
maxInMemory - 設定內存中創建對象的最大值。
eternal - 設置元素(譯注:內存中對象)是否永久駐留。如果是,將忽略超時限制且元素永不消亡。
timeToIdleSeconds - 設置某個元素消亡前的停頓時間。也就是在一個元素消亡之前,兩次訪問時間的最大時間間隔值。這只能在元素不是永久駐留時有效(譯注:如果對象永恆不滅,則設置該屬性也無用)。
如果該值是 0 就意味着元素可以停頓無窮長的時間。
timeToLiveSeconds - 為元素設置消亡前的生存時間。也就是一個元素從構建到消亡的最大時間間隔值。這只能在元素不是永久駐留時有效。
overflowToDisk  - 設置當內存中緩存達到maxInMemory 限制時元素是否可寫到磁盤上。

 

 

  1. 1.       ehcache使用了LinkedHashMap來存放Element。jdk要1.5以上。Ehcache1.5可以使用jdk1.4
  2. 如果在添加Elemtent時,緩存中的Element個數達到了最大緩存數並且overflowToDisk配置的屬性為true,Ehcache會更具配置項MemoryStoreEvictionPolicy的失效策略將Element輸出到磁盤。如果overflowToDisk為fasle,Ehcache將刪除內存中Element
  3. 值得注意的是緩存中失效的Element並不會別馬上清理掉,所以想得到內存的真實大小應該調用方法calculateInMemorySize()方法。
  4. 一個ehcache.xml對應一個CacheManager
  5. 不同的緩存應該對應不同的硬盤上的路徑,否則會報錯
  6. 注意要想使用磁盤緩存,緩存的Element必須實現序列化接口否則會拋出NotSerializableException異常。
  7. Ehcache會將每個緩存配置的文件路徑下創建一個cache_name.data文件,如果使用的磁盤持久化技術,還會生成一個cache name.index文件。
  8. 8.       Ehcache有一個后台線程專門做Ellment失效監測以及清除工作。設置線程運行間隔時間,可通過設置diskExpiryThreadIntervalSeconds屬性來完成,此值不宜設置過低,否則會導致清理線程占用大量CPU資源。默認值是120秒。
  9. 9.       持久化可在Element的diskPersistent配置項中配置,如果配置為“false”或是“omitted”在CacheManager shutdown或是startup后,用來緩存Element的文件將被清除掉。如果設置為“true”,data和index文件會被保存下來,對於新創建的CacheManager Element也是可用的。
  10. 使用時必須顯示調用cache. Flush()才會將數據緩存到磁盤中。
  11. 磁盤緩存步驟:從MemoryStore中把沒有失效的Element刷新到DiskStore,Element被寫入到data文件,Element將被序列化到index文件
  12. 12.   磁盤緩存大小默認是沒有限制的,不過可通過maxElementsOnDisk來指定。當磁盤緩存達到maxElementsOnDisk指定的值時,Ehcache會清理磁盤中的緩存使用默認策略是LFU(使用頻率最低)。
  13. 13.   在使用完Ehcache后,必須要shutdown緩存。Ehcache中有自己的關閉機制,不過最好在你的代碼中顯示調用CacheManager.getInstance().shutdown();
  14. 14.   Cache:對於getValue()能取到可序列化的值;getObjectValue()取得非序列化的值
  15. 15.   cache.getSize();得到緩存中元素的個數;獲得當前MemoryStore中的element數量:cache.getMemoryStoreSize();獲得當前DiskStore中element數量:cache.getDiskStoreSize();
  16. 16.   在使用完Ehcache后,必須要shutdown緩存。Ehcache中有自己的關閉機制,不過最好在你的代碼中顯示調用CacheManager.getInstance().shutdown();
  17. 17.   ehcache-core-1.6—1.7沒有任何依賴;ehcache1.7.1依賴SLF4J,以及相應的log的jar包。
  18. 18.   CacheManager可以通過單例(factory的靜態方法)或者構造函數(constructors)創建。分別叫做single model和instance model。當兩種情況都有的時候,系統會采用單例模式,構造器每次都生成單例模式
  19. 19.   對於想存儲數據到硬盤,或者集群時復制到其他緩存區域的數據,必須可序列化。如果不可序列化,該數據在進行上述操作時會被丟棄,且沒有報錯,只是在debug級別有日志信息。
  20. 20.   讀取cache的數據,有以下幾種方式:

Cache-aside: 直接操作數據

Cache-as-sor:read-through、write-through和write-behind的結合

Read-through:

Write-through:

Write-behind:

  1. 21.   從ehcache2.0開始,以下屬性可以在運行時改變:

• timeToLive

• timeToIdle

• maxElementsInMemory

• maxElementsOnDisk

• memory store eviciton policy

• CacheEventListeners can be added and removed dynamically []

   eternal屬性為“true”時,timeToLive和timeToIdle會失效

  1. 22.   以下代碼演示怎么運行時修改緩存屬性

This example shows how to dynamically modify the cache configuration of an already running cache:

Cache cache = manager.getCache("sampleCache");

CacheConfiguration config = cache.getCacheConfiguration();

config.setTimeToIdleSeconds(60);

config.setTimeToLiveSeconds(120);

config.setMaxElementsInMemory(10000);

config.setMaxElementsOnDisk(1000000);

 

Dynamic cache configurations can also be frozen to prevent future changes:

Cache cache = manager.getCache("sampleCache");

cache.disableDynamicFeatures();

  1. 23.   2.5之前是通過元素的個數來表示內存或者硬盤的大小2.5之后,通過字節數來表示。2.5暫時還沒有出來。新屬性將會是:

The new cache attributes are:

• maxBytesOnHeap

• maxBytesOffHeap (formerly maxMemoryOffHeap)

• maxBytesOnDisk

甚至,還可以指定比例,如:maxBytesOnHeap="20%".

  1. 24.   Ehcache可以將一些數據一直放到緩存或者堆棧或者硬盤或者terracotta的L2中。主要是為了滿足Hibernate等一些情況下的需求。但是,這樣很容易造成內存溢出的錯誤
  2. 25.   當緩存剛啟動時,ehcache提供一個機制可以先加載數據:BootstrapCacheLoader

 

class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"

properties="bootstrapAsynchronously=true"/>

 

DiskStoreBootstrapCacheLoaderFactory:從硬盤加載數據到堆棧

 

class="net.sf.ehcache.store.DiskStoreBootstrapCacheLoaderFactory"

properties="bootstrapAsynchronously=true"/>

 

TerracottaBootstrapCacheLoaderFactory:從terracotta的L2中加載數據

 

class="net.sf.ehcache.store.TerracottaStoreBootstrapCacheLoaderFactory"

properties="bootstrapAsynchronously=true"/>

  1. 26.   可以配置ehcache在讀或者寫的時候,做些事情。

CacheConfiguration config = new CacheConfiguration("copyCache", 1000).copyOnRead(true)

Cache copyCache = new Cache(config);

    默認此屬性是false

 

maxElementsInMemory="10"

eternal="false"

timeToIdleSeconds="5"

timeToLiveSeconds="10"

  • overflowToDisk="false"

copyOnRead="true"

copyOnWrite="true">

com.company.ehcache.MyCopyStrategy"/>

 

  1. 27.   每一個cache都有一個copyStrategy,所以,該實現是要求線程安全的

在ehcache啟動的時候,可以設置緩存失效。命令行啟動的時候如下:

java -Dnet.sf.ehcache.disabled=true

其他特殊的系統屬性:

1)java -Dnet.sf.ehcache.use.classic.lru=true

當LRU被選中的時候,更老的LruMemoryStore實現策略將會被真正采用

  1. 28.   ehcache.xml必須遵守ehcache.xsd文件中的要求
  2. 29.   當無參的構造函數,或者靜態構造方法被調用的時候,系統會在最頂層的classpath路徑下找名叫ehcache.xml的配置文件,如果查找失敗,會以jar包中的ehcache-failsafe.xml文件(里邊的緩存配置極其簡單)替代。同時,一個警告會提醒用戶建立自己的配置文件。
  3. 30.   Update checker可以檢查是否有最新的ehcache版本。有兩個辦法可以去掉該功能:

1)通過系統參數:-Dnet.sf.ehcache.skipUpdateCheck=true

2)通過配置文件:

xsi:noNamespaceSchemaLocation="ehcache.xsd"

updateCheck="false" monitoring="autodetect"

dynamicConfig="true">

  1. 31.   Ehcache1.6之前只支持ASCII編碼,之后,UTF-8也被支持。但UTF-8比ASCII更多落后,所以沒必要做專門的轉換
  2. 32.   每一個Cachemanager應該有自己的獨有的ehcache.xml配置文件。因為,當共用時,硬盤緩存路徑或者監聽端口將會沖突。系統也會發出警告,提醒用戶配置專門的配置文件為每一個cachemanager.在分布式系統中,ehcache.xml應該配置成一樣的。
  3. 33.   Ehcache有3個存儲:

1) 內存存儲

2) 非堆存儲(大內存,企業ehcache才擁有)

3) 硬盤存儲(兩個版本:開源的和企業級ehcache

  1. 34.   內存存儲

其本質是使用javaLinkedHashMap來實現的。多線程安全、內存管理安全、速度快

  1. 35.   calculateInMemorySize()可以用來計算當前ehcache內存占用大小。但生產線上不應該使用,因為這個功能效率非常低
  2. 36.   同時,ehcache內部有一個低等級的進程,它會判斷元素的是否過期。diskExpiryThreadIntervalSeconds屬性可以設置該線程執行的間隔時間(默認是120秒,不能太小,以免影響效率).
  3. 37.   非堆存儲

Terracotta BigMemory是一個新增的功能,它允許系統占用堆以外的內存,速度是硬盤存儲的100倍,允許很大的存儲空間被創建(350G被測試過)

因為非堆數據是以字節流的形式存儲,所以要求Element的key和value都要是可以序列化的。

因為序列化和反序列化的過程,這種存儲形式比內存存儲慢10

  1. 38.   硬盤存儲

線程安全的

  1. 39.   當maxElementsOnDisk被設置的時候,硬盤上的存儲達到限制時,LFU算法會被執行用於清除數據,只能是該算法,不可配置
  2. 40.   Persistence被設置成false或者omitted,當系統重啟時,不會硬盤的數據存儲在硬盤上,.data文件將會被刪除.相反,.data文件不會被刪除,下次重啟后Cachemanager還可以使用.data文件。
  3. 41.   虛擬機被停止的時候,強烈建議調用Cachemanager.shutdown()方法。
  4. 42.   在關閉java虛擬機時,系統執行以下步驟:

Considerations for guidance on how to safely shut the Virtual Machine down.

When a DiskStore is persisted, the following steps take place:

  • • Any non-expired Elements of the MemoryStore are flushed to the DiskStore
  • • Elements awaiting spooling are spooled to the data file
  • • The free list and element list are serialized to the index file

On startup the following steps take place:

  • • An attempt is made to read the index file. If it does not exist or cannot be read successfully, due to disk corruption, upgrade of ehcache, change in JDK version etc, then the data file is deleted and the DiskStore starts with no Elements in it.
  • • If the index file is read successfully, the free list and element list are loaded into memory. Once this is done, the index file contents are removed. This way, if there is a dirty shutdown, when restarted, Ehcache will delete the dirt index and data files.
  • • The DiskStore starts. All data is available.
  • • The expiry thread starts. It will delete Elements which have expired.
  1. 43.   一個示范性地配置:

把一個擁有8G機器內存的存儲分配成各種存儲。設想有一個7G的數據集,共7M個元素,每個元素1k大小。

我們設置1G的堆存儲和7G的非堆存儲:

java -Xms1G -Xmx1G -XX:maxDirectMemorySize=7G

對應的配置文件為:

 

maxElementsInMemory=100

overflowToOffHeap="true"(企業)

maxMemoryOffHeap="7G"

... />

  1. 44.   對於第二種集群方法,以下服務器被測試過:

• Glassfish V2/V3

• Tomcat 6

• Jetty 6

Tomcat 6通過了所有的繼集成測試

支持Weblogic10.3.2,但是SOAP不兼容。

  1. 45.   最大的Ehcache單實例在內存中可以緩存20GB,最大的磁盤可以緩存100GB
  2. 46.   關於ehcache server的相關命令用法在user guide的178
  3. 47.    

  

緩存屬性:

緩存配置。

以下屬性是必須的:

name - cache的標識符,在一個CacheManager中必須唯一

maxElementsInMemory - 在內存中緩存的element的最大數目

maxElementsOnDisk - 在磁盤上緩存的element的最大數目

eternal - 設定緩存的elements是否有有效期。如果為true,timeouts屬性被忽略

overflowToDisk - 設定當內存緩存溢出的時候是否將過期的element緩存到磁盤上

 

以下屬性是可選的:

timeToIdleSeconds - 緩存element在過期前的空閑時間。默認為0,表示可空閑無限時間. (如果指定了這個時間,是否在被hit的前超過了這個時間就會被remove?在內存緩存數目超限之前不會被remove)

timeToLiveSeconds - 緩存element的有效生命期。這個類似於timeouts,默認為0,不過期(是否通常情況下應該大於等於timeToIdleSeconds,小於會如何?idle時間也會減小和這個數值一樣)

diskPersistent - 在VM重啟的時候是否持久化磁盤緩存,默認是false。

(測試一下true的情況?重載vm的時候會從磁盤進行序列化到對象)

diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒.  (測試一下0的時候會如何)

memoryStoreEvictionPolicy - 當內存緩存達到最大,有新的element加入的時候,移除緩存中element的策略。默認是LRU,可選的有LFU和FIFO可對緩存中的element配置諸如監聽器和加載器。Ehcahe內建了一些

*cacheEventListenerFactory - 監聽緩存中element的put, remove, update和expire事件

*bootstrapCacheLoaderFactory - 啟動時加載緩存的element每個用來做分布式緩存都必須設定element的事件監聽器,用來在各個CacheManager節點復制消息。

Ehcache內建了基於RMI的實現 - RMICacheReplicatorFactory


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM