EhCache緩衝學習)

來源:互聯網
上載者:User

在看hibernate的官方文檔時,看到關於緩衝的介紹。

hibernate在緩衝管理上做的很好,具體使用,本章不做講解,本篇主要研究EhCache的用法。其中hibernate使用到的緩衝供應商列表如下:

 

Cache Provider class Type Cluster Safe Query Cache Supported
Hashtable (not intended for production use) org.hibernate.cache.HashtableCacheProvider memory   yes
EHCache org.hibernate.cache.EhCacheProvider memory, disk, transactional, clustered yes yes
OSCache org.hibernate.cache.OSCacheProvider memory,disk   yes
SwarmCache org.hibernate.cache.SwarmCacheProvider clustered (ip multicast) yes (clustered invalidation)  
JBoss Cache 1.x org.hibernate.cache.TreeCacheProvider clustered (ip multicast), transactional yes (replication) yes (clock sync req.)
JBoss Cache 2 org.hibernate.cache.jbc.JBossCacheRegionFactory clustered (ip multicast), transactional yes (replication or invalidation) yes (clock sync req.)


其中,我對EHCache比較感興趣。看它支援的類型包括對記憶體,硬碟,傳統,叢集都支援。

 

我們可以單獨研究一下Ehcache緩衝的使用,這樣方便以後我們對其他使用到緩衝的地方進行緩衝的自訂管理(不單單在hibernate查詢資料方面)。

 

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

先寫個例子,看看它的api如何使用:

 

EhcacheTest

 

package org.base.cache.test;import java.net.MalformedURLException;import java.net.URL;import net.sf.ehcache.Cache;import net.sf.ehcache.CacheManager;import net.sf.ehcache.Element;import net.sf.ehcache.config.CacheConfiguration;import net.sf.ehcache.config.Configuration;/** * Ehcache緩衝管理的api測試小例子 * @author lushuaiyin * */public class EhcacheTest {/** * @param args */public static void main(String[] args) throws MalformedURLException {net.sf.ehcache.config.Configuration config=new Configuration();//如果不使用ehcache.xml設定檔,那麼必須用代碼配置一個defaultCacheConfigurationCacheConfiguration defaultCacheConfiguration=new CacheConfiguration();defaultCacheConfiguration.setMaxEntriesLocalHeap(0);defaultCacheConfiguration.setEternal(false);defaultCacheConfiguration.setTimeToIdleSeconds(30);defaultCacheConfiguration.setTimeToLiveSeconds(30);config.addDefaultCache(defaultCacheConfiguration);//設定預設cachenet.sf.ehcache.CacheManager cacheManager=CacheManager.create(config);//建立緩衝資訊/*構造方法有多種,詳見文檔 public Cache(String name,             int maxElementsInMemory,             boolean overflowToDisk,             boolean eternal,             long timeToLiveSeconds,             long timeToIdleSeconds) *///自訂配置緩衝net.sf.ehcache.Cache cache1=new Cache("mycache-one", 1000, false, false, 30, 30);cacheManager.addCache(cache1);//只有配置了defaultCacheConfiguration,這個方法才可以使用。因為用字串命名的緩衝必須有實際配置。cacheManager.addCache("mycache-two");//添加一個空緩衝//往緩衝中放值String objkey1="key1",objvalue1="value1";cache1.put(new Element(objkey1,objvalue1));//直接放//遍曆取出某個緩衝中的所有值if(cacheManager.getCache("mycache-one")!=null){Cache cache11=cacheManager.getCache("mycache-one");if(cache11.getKeys().size()==0){System.out.println("mycache-one exits,but no value.");}else{for(int i=0;i<cache11.getKeys().size();i++){Object thekey=cache11.getKeys().get(i);Object thevalue=cache11.get(thekey);System.out.println("mycache-one-"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());}}}else{System.out.println("mycache-one-is null");}/*列印mycache-one-0,key:key1,value:[ key = key1, value=value1, version=1, hitCount=1, CreationTime = 1366263629054, LastAccessTime = 1366263629054 ] */if(cacheManager.getCache("mycache-two")!=null){Cache cache2=cacheManager.getCache("mycache-two");if(cache2.getKeys().size()==0){System.out.println("mycache-two exits,but no value.");}else{for(int i=0;i<cache2.getKeys().size();i++){Object thekey=cache2.getKeys().get(i);Object thevalue=cache2.get(thekey);System.out.println("mycache-two-"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());}}}else{System.out.println("mycache-two-is null");}/*列印mycache-two exits,but no value. */}}

 

Ehcache在使用的大多數情況,是用ehcache.xml來配置的。在spring中的整合很方便。

下面我們使用ehcache.xml,但不在web環境下,對緩衝進行自訂。

org/base/cache/test/myehcache.xml

 

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="ehcache.xsd"         updateCheck="true" monitoring="autodetect"         dynamicConfig="true">        <diskStore path="java.io.tmpdir"/>        <!-- JTA事務配置。class屬性若為空白,則預設會按照一個順序尋找TransactionManager對象。              也可以自訂,需要實現介面net.sf.ehcache.transaction.manager.TransactionManagerLookup    -->    <!--    <transactionManagerLookup class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"                              properties="jndiName=java:/TransactionManager" propertySeparator=";"/>    -->    <!-- CacheManagerEventListener  緩衝監聽,根據需要自訂監聽類      <cacheManagerEventListenerFactory class="" properties=""/>    -->        <!-- Terracotta伺服器叢集配置,詳細看文檔 -->    <!--    <terracottaConfig url="localhost:9510"/>    -->        <defaultCache           maxEntriesLocalHeap="0"           eternal="false"           timeToIdleSeconds="30"           timeToLiveSeconds="30">     <!-- <terracotta/>-->    </defaultCache>    <!--           緩衝名為myCache1,    這個緩衝最多包含10000個元素在記憶體中,並將    閑置超過5分鐘和存在超過10分鐘的元素釋放。    如果超過10000元素,將溢流到磁碟緩衝,並且硬碟緩衝最大數量是1000.           硬碟路徑是定義的java.io.tmp。    -->    <cache name="myCache1"           maxEntriesLocalHeap="500"           maxEntriesLocalDisk="1000"           eternal="false"           diskSpoolBufferSizeMB="20"           timeToIdleSeconds="300"           timeToLiveSeconds="600"           memoryStoreEvictionPolicy="LFU"           transactionalMode="off">        <persistence strategy="localTempSwap"/>    </cache>    <!--            緩衝名為sampleCache2。    此緩衝在記憶體中最大元素的數量是1000。            沒有設定溢出到磁碟,所以1000就是這個緩衝的最大值。            注意,當一個緩衝eternal設定成true,那麼TimeToLive    和timeToIdle江不起作用。        <cache name="sampleCache2"           maxEntriesLocalHeap="1000"           eternal="true"           memoryStoreEvictionPolicy="FIFO"/>-->    <!--            緩衝名為sampleCache3的。           這個緩衝溢出會到磁碟。磁碟緩衝儲存在虛擬機器重新啟動前會持久有效。           磁碟的終止線程的時間間隔設定為3分鐘,覆蓋預設的2分鐘。         <cache name="sampleCache3"           maxEntriesLocalHeap="500"           eternal="false"           overflowToDisk="true"           diskPersistent="true"           timeToIdleSeconds="300"           timeToLiveSeconds="600"           diskExpiryThreadIntervalSeconds="180"           memoryStoreEvictionPolicy="LFU">    </cache>-->    <!--     Terracotta叢集緩衝sampleTerracottaCache。         <cache name="sampleTerracottaCache"           maxBytesLocalHeap="10m"           eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="1800">        <terracotta/>    </cache>-->        </ehcache>

 

 

關於配置的屬性的含義,可以到官網的文檔中查看,這裡給出一些常用的屬性。

 

    Cache的以下屬性是必須的。    name:    cache的唯一標識。    maxEntriesLocalHeap:    在記憶體建立對象的最大數量。0=無限制。    無限制實際指Integer.MAX_SIZE (2147483647)。    maxEntriesLocalDisk:    設定在硬碟上儲存的對象的最大數量。預設0,即無限制。    eternal:    設定元素是否持久化。如果是,元素不會到期。    Cache的以下屬性是可選的。    overflowToOffHeap:    此功能僅在企業版的Ehcache。    當設定為true,可利用無限制的離堆記憶體的緩衝    儲存,以提高效能。離堆記憶體是不受Java    GC限制的。預設值是false。    maxBytesLocalHeap:    定義多少位元組緩衝可能會使用虛擬機器的堆。如果一個CacheManager的    maxBytesLocalHeap已經被定義,這個緩衝的指定金額將    減去從CacheManager的。其他的快取將分享剩下的人。    此屬性的值是<數字> K | K |米| M| G| G    KB(K| K),MB(M| M)或千MB(G| G)。    例如,maxBytesLocalHeap的“2G”下發2 GB的堆記憶體。    如果您指定一個maxBytesLocalHeap,就不能再使用屬性maxEntriesLocalHeap。    maxBytesLocalOffHeap:    此功能僅在企業版的Ehcache。    離堆記憶體量,可以使用這個緩衝設定,將保留。    此設定將設定overflowToOffHeap為true 。設定explicitly為false來禁用溢出行為。    需要注意的是使用時離堆,設定maxEntriesLocalHeap建議至少100個元素,    否則效能會出現嚴重退化,並提出警告。    可分配的最低金額為128MB。沒有最大值。    maxBytesLocalDisk:    As for maxBytesLocalHeap, but specifies the limit of disk storage this cache will ever use.    timeToIdleSeconds:    設定元素閑置時間長度。單位:秒。(在eternal設定成false的情況下有效)    可選屬性。值為0意味著元素可以閑置無窮。    預設值是0。    timeToLiveSeconds:    設定元素到期時間長度。單位:秒。(在eternal設定成false的情況下有效)    可選屬性。值為0意味著,元素可以住無窮。    預設值是0。    diskExpiryThreadIntervalSeconds:    磁碟到期線程運行之間的秒數。預設值為120秒。    diskSpoolBufferSizeMB:    這是分配硬碟儲存的緩衝區的大小。資訊被寫入    這個地區,然後非同步寫入到磁碟中。預設大小為30MB。    每個緩衝區僅用於由其緩衝。如果你遇到記憶體溢出錯誤試著    降低此值。為了提高硬碟儲存效能應考慮增加此值。    clearOnFlush:    調用flush()方法時,硬碟儲存緩衝被清除。    預設值是true。    memoryStoreEvictionPolicy:    記憶體管理原則,預設是最近最少使用原則(即Least Recently Used,LRU)。    其他可選的有先進先出策略(即 First In First Out,FIFO),最少使用頻率策略    (即Less Frequently Used,LFU)。    copyOnRead:    一個元素被複製時是否從緩衝中讀取。    預設false。    copyOnWrite:    一個元素被添加到緩衝中時是否被複製。    預設false。

 


EhcacheManagerTest

 

package org.base.cache.test;import java.net.URL;import net.sf.ehcache.Cache;import net.sf.ehcache.CacheManager;import net.sf.ehcache.Element;import net.sf.ehcache.Status;/** * Ehcache緩衝管理的初步學習執行個體 * @author lushuaiyin * */public class EhcacheManagerTest {public static net.sf.ehcache.CacheManager cacheManager = null;private static String configPath="org/base/cache/test/myehcache.xml";//設定檔路徑,一般會放在源檔案夾private static String CACHE_MYCACHE1="myCache1";//定義檔案中配置的緩衝//執行個體化cacheManager,單例模式public static CacheManager getCacheManagerInstance(){if (cacheManager == null) {URL configUrl=null;configUrl = EhcacheManagerTest.class.getClassLoader().getResource(configPath);cacheManager = CacheManager.create(configUrl);}return cacheManager;}public static net.sf.ehcache.CacheManager getCacheManager() {return getCacheManagerInstance();//單例緩衝管理}//這個set可以不開放public static void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {EhcacheManagerTest.cacheManager = cacheManager;}//添加新緩衝public static void addCacheByName(String cacheName){if(cacheName==null||cacheName.trim().equals("")){System.out.println("cacheName is null");}else{if(getCacheManager().getCache(cacheName.trim())!=null){getCacheManager().removeCache(cacheName.trim());}getCacheManager().addCache(cacheName.trim());System.out.println(cacheName+ "重新添加");}}//得到cache對象public static Cache getCacheByName(String cacheName){Cache cache=null;if(cacheName==null||cacheName.trim().equals("")){System.out.println("cacheName is null");}else{if(getCacheManager().getCache(cacheName.trim())!=null){cache=getCacheManager().getCache(cacheName.trim());}}return cache;}//往緩衝中添加元素public static void putElementToCache(String cacheName,String elementKey,Object elementValue){Cache cache=null;if(cacheName==null||cacheName.trim().equals("")){System.out.println("添加緩衝元素失敗,cacheName is null");}else if(elementKey==null||elementValue==null){System.out.println("添加緩衝元素失敗,elementKey or elementValue is null");}else{if(getCacheByName(cacheName.trim())!=null){//緩衝存在cache=getCacheByName(cacheName.trim());}else{//緩衝不存在addCacheByName(cacheName.trim());cache=getCacheByName(cacheName.trim());}//對cache對象添加ElementElement element=null;if(cache.get(elementKey.trim())!=null){cache.remove(elementKey.trim());}element=new Element(elementKey.trim(),elementValue);cache.put(element);System.out.println("添加緩衝元素:"+elementKey+"成功!");}}//從緩衝中擷取指定key的值public static Object getElementValueFromCache(String cacheName,String elementKey){Object result=null;Cache cache=null;if(cacheName==null||cacheName.trim().equals("")){System.out.println("擷取緩衝元素失敗,cacheName is null");}else if(elementKey==null){System.out.println("擷取緩衝元素失敗,elementKey  is null");}else{if(getCacheByName(cacheName.trim())!=null){//緩衝存在cache=getCacheByName(cacheName.trim());Element element=null;if(cache.get(elementKey.trim())!=null){element=cache.get(elementKey.trim());if(element.getObjectValue()==null){System.out.println("緩衝中"+elementKey+" 的值為空白.");}else{result=element.getObjectValue();}}else{System.out.println("緩衝中"+elementKey+" 的Element值為空白.");}}else{//緩衝不存在System.out.println("擷取緩衝元素失敗,緩衝"+cacheName+" 為空白.");}}return result;}/** * 把所有cache中的內容刪除,但是cache對象還是保留. * Clears the contents of all caches in the CacheManager, *  but without removing any caches. */public static void clearAllFromCacheManager(){if(getCacheManager()!=null){getCacheManager().clearAll();System.out.println("CacheManager was clearAll...");}} /** * 把所有cache對象都刪除。慎用! * Removes all caches using removeCache(String) for each cache. */public static void removalAllFromCacheManager(){if(getCacheManager()!=null){getCacheManager().removalAll();System.out.println("CacheManager was removalAll...");}} //不用緩衝時,要關閉,不然會佔用cpu和記憶體資源。public static void shutdownCacheManager(){if(getCacheManager()!=null){getCacheManager().shutdown();System.out.println("CacheManager was shutdown...");}}//列印方法1,為了測試用public static void printCache(Cache cache){System.out.println("緩衝狀態: "+cache.getStatus().toString());if(cache==null){System.out.println("cache is null,no print info.");}else if(cache.getStatus().toString().equals(Status.STATUS_UNINITIALISED)){System.out.println("緩衝狀態: 未初始化"+cache.getStatus().toString());}else if(cache.getStatus().toString().equals(Status.STATUS_SHUTDOWN)){System.out.println("緩衝狀態: 已關閉"+cache.getStatus().toString());}else if(cache.getStatus().toString().equals(Status.STATUS_ALIVE)){if(cache.getKeys().size()==0){System.out.println(cache.getName()+" exits,but no value.");}else{for(int i=0;i<cache.getKeys().size();i++){Object thekey=cache.getKeys().get(i);Object thevalue=cache.get(thekey);System.out.println(cache.getName()+"--"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());}}}}//列印方法2,為了測試用public static void printCacheByName(String cacheName){if(cacheName==null||cacheName.trim().equals("")){System.out.println("cacheName is null,no print info.");}else{if(getCacheManager().getCache(cacheName.trim())!=null){Cache cache=getCacheManager().getCache(cacheName.trim());printCache(cache);}else{System.out.println(cacheName+" --null");}}}public static void main(String[] sdfsf){Cache cache1=EhcacheManagerTest.getCacheByName(EhcacheManagerTest.CACHE_MYCACHE1);printCache(cache1);EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "111", "111haah");EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "222", "222haah");EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "333", "333haah");printCache(cache1);EhcacheManagerTest.putElementToCache(EhcacheManagerTest.CACHE_MYCACHE1, "111", "111的新值。");System.out.println(EhcacheManagerTest.getElementValueFromCache(EhcacheManagerTest.CACHE_MYCACHE1, "111"));printCache(cache1);clearAllFromCacheManager();printCache(cache1);removalAllFromCacheManager();printCache(cache1);shutdownCacheManager();}/*列印緩衝狀態: STATUS_ALIVE添加緩衝元素:111成功!添加緩衝元素:222成功!添加緩衝元素:333成功!緩衝狀態: STATUS_ALIVE添加緩衝元素:111成功!111的新值。緩衝狀態: STATUS_ALIVECacheManager was clearAll...緩衝狀態: STATUS_ALIVECacheManager was removalAll...緩衝狀態: STATUS_SHUTDOWNCacheManager was shutdown... */}

 

通過上面的使用,我們初步瞭解Ehcache的api。在web環境下,我們可以注入EhcacheManager對象,

把需要的資料,放入緩衝。在其他地方取資料的時候,就從過EhcacheManager來擷取,而不是直接

從資料庫查詢。這樣就提高了效率。

 

值得注意的是,緩衝的使用一般在一些資料比較固定的地方。如果某個查詢需要保證資料的即時性,使用緩衝

就是錯誤的做法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.