EHCache學習筆記1


介紹:

EHCache 是一個快速的、輕量級的、易於使用的、進程內的緩存。它支持 read-only read/write 緩存,內存和磁盤緩存。是一個非常輕量級的緩存實現,而且從 1.2 之后就支持了集群。

配置:

    EHCache的配置非常靈活,可以在聲明里配置,也可以在xml、程序中、構造函數中配置。下面在程序中動態的改變Cache的配置,如下:

Cache cache = manager.getCache("sampleCache");
CacheConfiguration config = cache.getCacheConfiguration();
config.setTimeToIdleSeconds(60);
config.setTimeToLiveSeconds(120);
config.setmaxEntriesLocalHeap(10000);
config.setmaxEntriesLocalDisk(1000000);

當然也可以凍結動態的Cache的配置,如下:

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

xml中將 <ehcache> 元素的屬性 dynamicConfigattribute 改為 "false"即可。

 

多層次CacheCache Warming

要在緩存啟動的時候同步緩存數據。EHCache2.5以上版本提供了支持,如下:

Replicated caches provide a boot strap mechanism which populates them. For example following is the JGroups bootstrap cache loader:

<bootstrapCacheLoaderFactory

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

properties="bootstrapAsynchronously=true"/>

There are two new bootstrapCacheLoaderFactory implementations: one for standalone caches with DiskStores, and one for Terracotta Distributed caches.

 

DiskStoreBootstrapCacheLoaderFactory

The DiskStoreBootstrapCacheLoaderFactory loads elements from the DiskStore to the On-Heap Store and the Off-Heap store until either:

<bootstrapCacheLoaderFactory

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

properties="bootstrapAsynchronously=true"/>

 

TerracottaBootstrapCacheLoaderFactory

The TerracottaBootstrapCacheLoaderFactory loads elements from the Terracotta L2 to the L1 based on what it was using the last time it ran. If this is the first time it has been run it has no effect.

<bootstrapCacheLoaderFactory class="net.sf.ehcache.terracotta.TerracottaBootstrapCacheLoaderFactory"

properties="bootstrapAsynchronously=true,

directory=dumps,

interval=5,

immediateShutdown=false,

snapshotOnShutDown=true,

doKeySnapshot=false,

useDedicatedThread=false"/>

當然EHCachecache也可以配置讀拷貝與寫拷貝,詳細見:copyOnRead and copyOnWrite cache configuration

 

ehcache.xml的配置

EHCache默認到classpath下去找ehcache.xml,如果找不到,則找ehcache-failsafe.xml配置文件,而ehcache-failsafe.xml是打包在的ehcachejar包中,所以它始終可以被找到。ehcache-failsafe.xml提供了一個非常簡單的默認配置,它允許用戶在配置chcache.xml之前就可以啟動ehcache,其中的配置如下:

<ehcache>

<diskStore path="java.io.tmpdir"/>

<defaultCache

maxEntriesLocalHeap="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

maxEntriesLocalDisk="10000000"

diskPersistent="false"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU"

/>

</ehcache>

 

BigMemory的介紹與配置

    BigMemory是一個純的java產品,它支持caches使用額外的內存空間來存儲堆對象,它以快照式的任務存儲(或稱off-heap store,離線堆存儲),打包在Enterprise Ehcache中,This off-heap store, which is not subject to Java GC, is 100 times faster than the DiskStore and allows very large caches to be created (we have tested this with over 350GB).

 

配置(Configuring caches to overflow to off-heap.)

 

Declarative Configuration-說明性的配置(通過xml配置文件)

<ehcache updateCheck="false" monitoring="off" dynamicConfig="false">

<defaultCache maxEntriesLocalHeap="10000"

eternal="true"

memoryStoreEvictionPolicy="LRU"

statistics="false" />

 

<cache name="sample-offheap-cache"

maxEntriesLocalHeap="10000"

eternal="true"

memoryStoreEvictionPolicy="LRU"

overflowToOffHeap="true"

maxMemoryOffHeap="1G"/>

</ehcache>

 

注意,NOTE: Dynamically Adding Caches With Fixed-Sized Offheap

If a CacheManager has a pooled offheap setting, caches with fixed-size offheap settings cannot be added dynamically. Dynamic in this case refers to caches that are added programmatically or using the Terracotta Developer Console while the CacheManager is running. A fixed-size offheap setting refers to a setting that specifies a size in bytes.

 

Programmatic Configuration(程序中配置)

public Cache createOffHeapCache()
{
  CacheConfiguration config = new CacheConfiguration("sample-offheap-cache", 10000)
  .overflowToOffHeap(true).maxMemoryOffHeap("1G");
  Cache cache = new Cache(config);
  manager.addCache(cache);
  return cache;
}

 

sizing caches

Tuning Ehcache often involves sizing cached data appropriately. Ehcache provides a number of ways to size the different data tiers using simple cache-configuration sizing attributes. These sizing attributes affect local memory and disk resources, allowing them to be set differently on each node.(翻譯:調諧Ehcache常常涉及sizing cached 數據的合適性。Ehcache提供了大量的方式配置不同的數據層的大小,使用簡單的cache-configuration sizing 屬性。這些 sizing 屬性會影響本地內存和磁盤資源,對於每個節點允許它們設置不同。)

 

使用ehcache

cache取值與設值

示例1

public class MyDataAccessClass
{
  private final Ehcache cache;
  public MyDataAccessClass(Ehcache cache)
  {
    this.cache = cache;
  }

  /* read some data, check cache first, otherwise read from sor */
  public V readSomeData(K key)
  {
     Element element;
     if ((element = cache.get(key)) != null) {
         return element.getValue();
     }
      // note here you should decide whether your cache
     // will cache 'nulls' or not
     if (value = readDataFromDataStore(key)) != null) {
         cache.put(new Element(key, value));
     }
     return value;
  }
  /* write some data, write to sor, then update cache */
  public void writeSomeData(K key, V value)
  {
     writeDataToDataStore(key, value);
     cache.put(new Element(key, value);
  }

 

    示例2

public class MyDataAccessClass

{

private final Ehcache cache;

public MyDataAccessClass(Ehcache cache)

{

cache.registerCacheWriter(new MyCacheWriter());

this.cache = new SelfPopulatingCache(cache);

}

/* read some data - notice the cache is treated as an SOR.

* the application code simply assumes the key will always be available

*/

public V readSomeData(K key)

{

return cache.get(key);

}

/* write some data - notice the cache is treated as an SOR, it is

* the cache's responsibility to write the data to the SOR.

*/

public void writeSomeData(K key, V value)

{

cache.put(new Element(key, value);

}

/**

* Implement the CacheEntryFactory that allows the cache to provide

* the read-through strategy

*/

private class MyCacheEntryFactory implements CacheEntryFactory

{

public Object createEntry(Object key) throws Exception

{

return readDataFromDataStore(key);

}

}

/**

* Implement the CacheWriter interface which allows the cache to provide

* the write-through or write-behind strategy.

*/

private class MyCacheWriter implements CacheWriter

public CacheWriter clone(Ehcache cache) throws CloneNotSupportedException;

{

throw new CloneNotSupportedException();

}

public void init() { }

void dispose() throws CacheException { }

void write(Element element) throws CacheException;

{

writeDataToDataStore(element.getKey(), element.getValue());

}

void writeAll(Collection elements) throws CacheException

{

for (Element element : elements) {

write(element);

}

}

void delete(CacheEntry entry) throws CacheException

{

deleteDataFromDataStore(element.getKey());

}

void deleteAll(Collection entries) throws CacheException

{

for (Element element : elements) {

delete(element);

}

}

}

}

 

示例3

EHCacheUtils.java

package com.ttpod.common.tool.cache;

 

/**

* @classDescription:ehcache工具類

*/

 

public class EHCacheUtil {

    private static CacheManager cacheManager = null;

    private static Cache cache=null;

//------------------簡化---------------------

    /**

     * 初始化緩存管理容器

     */

    public static CacheManager initCacheManager() {

        try {

            if (cacheManager == null)

                cacheManager = CacheManager.getInstance();

            

        } catch (Exception e) {

            e.printStackTrace();

        }

        return cacheManager;

    }

 

    /**

     * 初始化緩存管理容器

     * @param path ehcache.xml存放的路徑

     */

    public static CacheManager initCacheManager(String path) {

        try {

            

            if (cacheManager == null){

                System.out.println("為進來"+path);

                cacheManager = CacheManager.getInstance().create(path);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return cacheManager;

    }

    

    /**

     * 初始化cache

     */

    public static Cache initCache(String cacheName) {

        checkCacheManager();

        

        if(null==cacheManager.getCache(cacheName)){

            cacheManager.addCache(cacheName);

        }

        cache=cacheManager.getCache(cacheName);

        return cache;

    }

    

    /**

     * 添加緩存

     * @param key 關鍵字

     * @param value

     */

    public static void put(Object key,Object value) {

        checkCache();

        // 創建Element,然后放入Cache對象中

        Element element = new Element(key, value);

        cache.put(element);

    }

    /**

     * 獲取cache

     * @param key 關鍵字

     * @return

     */

    public static Object get(Object key){

        checkCache();

        Element element = cache.get(key);

        if(null==element){

            return null;

        }

        return element.getObjectValue();

    }

    //--------------更加方便使用的----------------

    //private static CacheManager myManager=null;

    //private static Cache myCache=null;

    

    /**

     * 初始化緩存

     * @param cacheName 緩存名稱

     * @param maxElementsInMemory 元素最大數量

     * @param overflowToDisk 是否持久化到硬盤

     * @param eternal 是否會死亡

     * @param timeToLiveSeconds 緩存存活時間

     * @param timeToIdleSeconds 緩存的間隔時間

     * @return緩存

     * @throws Exception 異常

     */

    public static Cache initCache(String cacheName,int maxElementsInMemory,

            boolean overflowToDisk,boolean eternal,long timeToLiveSeconds,

            long timeToIdleSeconds) throws Exception{

        try {

            CacheManager singletonManager = CacheManager.create();

            Cache myCache = singletonManager.getCache(cacheName);

            if(myCache!=null){

                CacheConfiguration config = cache.getCacheConfiguration();

                config.setTimeToLiveSeconds(timeToLiveSeconds);

                config.setMaxElementsInMemory(maxElementsInMemory);

                config.setOverflowToDisk(overflowToDisk);

                config.setEternal(eternal);

                config.setTimeToLiveSeconds(timeToLiveSeconds);

                config.setTimeToIdleSeconds(timeToIdleSeconds);

            }

            if(myCache==null){

                Cache memoryOnlyCache = new Cache(cacheName, maxElementsInMemory, overflowToDisk,

                        eternal, timeToLiveSeconds, timeToIdleSeconds);

                singletonManager.addCache(memoryOnlyCache);

                myCache = singletonManager.getCache(cacheName);

            }

            return myCache;

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("init cache "+cacheName+" failed!!!");

        }

    }

    

    /**

     * 初始化cache

     * @param cacheName cache的名字

     * @param timeToLiveSeconds 有效時間

     * @return cache 緩存

     * @throws Exception 異常

     */

    public static Cache initCache(String cacheName,long timeToLiveSeconds) throws Exception{

        try {

            CacheManager myManager = CacheManager.create();

            Cache myCache = myManager.getCache(cacheName);

            if(myCache!=null){

                CacheConfiguration config = myCache.getCacheConfiguration();

                config.setTimeToLiveSeconds(timeToLiveSeconds);

                config.setMaxElementsInMemory(EHCacheConfig.MAXELEMENTSINMEMORY);

                config.setMemoryStoreEvictionPolicy(EHCacheConfig.MEMORYSTOREEVICTIONPOLICY);

                config.setOverflowToDisk(EHCacheConfig.OVERFLOWTODISK);

                config.setEternal(EHCacheConfig.ETERNAL);

                config.setTimeToLiveSeconds(timeToLiveSeconds);

                config.setTimeToIdleSeconds(EHCacheConfig.TIMETOIDLESECONDS);

                config.setDiskPersistent(EHCacheConfig.DISKPERSISTENT);

                config.setDiskExpiryThreadIntervalSeconds(0);

            }

            if(myManager.getCache(cacheName)==null){

                myCache = new Cache(

                 new CacheConfiguration(cacheName, EHCacheConfig.MAXELEMENTSINMEMORY)

                 .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)

                 .overflowToDisk(EHCacheConfig.OVERFLOWTODISK)

                 .eternal(EHCacheConfig.ETERNAL)

                 .timeToLiveSeconds(timeToLiveSeconds)

                 .timeToIdleSeconds(EHCacheConfig.TIMETOIDLESECONDS)

                 .diskPersistent(EHCacheConfig.DISKPERSISTENT)

                 .diskExpiryThreadIntervalSeconds(0));

                myManager.addCache(myCache);

            }

            return myCache;

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("init cache "+cacheName+" failed!!!");

        }

    }

    

    /**

     * 修改緩存

     * @param cacheName 緩存名

     * @param timeToLiveSeconds 有效時間

     * @param maxElementsInMemory 最大數量

     * @return

     * @throws Exception 異常

     */

    public static boolean modifyCache(String cacheName,

            long timeToLiveSeconds,int maxElementsInMemory) throws Exception{

        try {

            if(StringUtils.isNotBlank(cacheName) && timeToLiveSeconds!=0L

                    && maxElementsInMemory!=0){

                CacheManager myManager = CacheManager.create();

                Cache myCache = myManager.getCache(cacheName);

                CacheConfiguration config = myCache.getCacheConfiguration();

                config.setTimeToLiveSeconds(timeToLiveSeconds);

                config.setMaxElementsInMemory(maxElementsInMemory);

                return true;

            }else{

                return false;

            }

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("modify cache "+cacheName+" failed!!!");

        }

    }

    

    /**

     * 請求向ehcache中設置值

     * @param vesselName 容器名

     * @param key

     * @param value

     * @return返回真

     * @throws Exception 異常

     */

    public static boolean setValue(String cacheName,String key, Object value) throws Exception{

        try {

            EHCacheUtil.initCacheManager();

            EHCacheUtil.initCache(cacheName);

            EHCacheUtil.put(key, value);

            //cacheManager.

            return true;

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("set cache "+cacheName+" failed!!!");

        }

    }

    

    /**

     * ehcache的指定容器中取值

     * @param key

     * @return返回Object類型的值

     * @throws Exception 異常

     */

    public static Object getValue(String cacheName,String key) throws Exception{

        try {

            EHCacheUtil.initCacheManager();

            EHCacheUtil.initCache(cacheName);

            return EHCacheUtil.get(key);

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("get cache "+cacheName+" failed!!!");

        }

    }

    

    /**

     * 刪除指定的ehcache容器

     * @param vesselName

     * @return

     * @throws Exception 異常

     */

    public static boolean removeEhcache(String cacheName) throws Exception{

        try {

            initCacheManager();

            initCache(cacheName);

            removeCache(cacheName);

            return true;

        } catch (Exception e) {

            e.printStackTrace();

            throw new Exception("remove cache "+cacheName+" failed!!!");

        }

    }

    //------------------方便調用------------

    /**

     * 釋放CacheManage

     *

     */

    public static void shutdown() {

        cacheManager.shutdown();

    }

    

    /**

     * 移除cache

     * @param cacheName

     */

    public static void removeCache(String cacheName){

        checkCacheManager();

        cache=cacheManager.getCache(cacheName);

        if(null!=cache){

            cacheManager.removeCache(cacheName);

        }

        

    }

    /**

     * 移除cache中的key

     * @param cacheName

     */

    public static void remove(String key){

        checkCache();

        cache.remove(key);

 

    }

    

    /**

     * 移除所有cache

     */

    public static void removeAllCache(){

        checkCacheManager();

        cacheManager.removalAll();

    }

    

    /**

     * 移除所有Element

     */

    public static void removeAllKey(){

        checkCache();

        cache.removeAll();

    }

    

    /**

     * 獲取所有的cache名稱

     * @return

     */

    public static String[]getAllCaches(){

        checkCacheManager();

        return cacheManager.getCacheNames();

    }

    /**

     * 獲取Cache所有的Keys

     * @return

     */

    public static List getKeys(){

        checkCache();

        return cache.getKeys();

    }

 

    /**

     * 檢測cacheManager

     */

    private static void checkCacheManager(){

        if(null==cacheManager){

            throw new IllegalArgumentException("調用前請先初始化CacheManager值:EHCacheUtil.initCacheManager");

        }

        

    }

    

    private static void checkCache(){

        if(null==cache){

            throw new IllegalArgumentException("調用前請先初始化Cache值:EHCacheUtil.initCache(參數)");

        }

    }

    

    public static void main(String[]arg){

        //初始化--必須

        EHCacheUtil.initCacheManager();

        String[]caches=EHCacheUtil.getAllCaches();

        for(String cache:caches){

            System.out.println(cache);

        }

//        //放入Test Cache

//        EHCacheUtil.initCache("ceshi");

//        EHCacheUtil.put("F", "hello world");

//        //--1111

//        System.out.println(EHCacheUtil.get("F"));

//    

//        

//        EHCacheUtil.initCacheManager();

//        EHCacheUtil.initCache("Test");

//        EHCacheUtil.put("F", "hello world1");

//        

//        //----2222

//        System.out.println(EHCacheUtil.get("F"));

//        

//        //初始化--必須

//        EHCacheUtil.initCacheManager();

//        //放入Test Cache

//        EHCacheUtil.initCache("ceshi");

//        //----3333

//        System.out.println(EHCacheUtil.get("F"));

//        

//        

//        //初始化--必須

//        EHCacheUtil.initCacheManager();

//        //放入Test Cache

//        EHCacheUtil.initCache("cassger");

//        //----

//        EHCacheUtil.put("F", "fangs");

//        System.out.println(EHCacheUtil.get("F"));

        

    }

}

 

EHCacheConfig.java

package com.ttpod.common.tool.cache;

/**

* @className:EHCacheConfig.java

* @classDescription:

*/

public class EHCacheConfig {

    /**

     * 元素最大數量

     */

    public static int MAXELEMENTSINMEMORY=50000;

    /**

     * 是否把溢出數據持久化到硬盤

     */

    public static boolean OVERFLOWTODISK=true;

    /**

     * 是否會死亡

     */

    public static boolean ETERNAL=false;

    /**

     * 緩存的間隔是時間

     */

    public static int TIMETOIDLESECONDS=300;

    /**

     * 需要持久化到硬盤否

     */

    public static boolean DISKPERSISTENT=false;

    /**

     * 內存存取策略

     */

    public static String MEMORYSTOREEVICTIONPOLICY="LFU";

 

}

 

hibernate中的二級緩存

命名緩存查詢

In addition, a QueryCache can be given a specific name in Hibernate using Query.setCacheRegion(String name). The name of the cache in ehcache.xml is then the name given in that method. The name can be whatever you want, but by convention you should use "query." followed by a descriptive name. E.g.

<cache name="query.AdministrativeAreasPerCountry"

maxEntriesLocalHeap="5"

eternal="false"

timeToLiveSeconds="86400"

overflowToDisk="true"/>

 

使用緩存查詢

For example, let's say we have a common query running against the Country Domain. Code to use a query cache follows:

public List getStreetTypes(final Country country) throws HibernateException {

final Session session = createSession();

try {

final Query query = session.createQuery(

"select st.id, st.name"

+ " from StreetType st "

+ " where st.country.id = :countryId "

+ " order by st.sortOrder desc, st.name");

query.setLong("countryId", country.getId().longValue());

query.setCacheable(true);

query.setCacheRegion("query.StreetTypes");

return query.list();

} finally {

session.close();

}

}

The query.setCacheable(true) line caches the query.Thequery.setCacheRegion("query.StreetTypes") line sets the name of the Query Cache. Alex Miller has a good article on the query cache here.

 

程序中配置ehcache

 

 

Differences Between Distributed Cache and Standalone or Replicated Cache

CacheManagers can be configured programmatically with a fluent API. The example below creates a CacheManager with a Terracotta configuration specified in an URL, and creates a defaultCache and a cache named "example".

Configuration configuration = new Configuration()
.terracotta(new TerracottaClientConfiguration().url("localhost:9510"))
.defaultCache(new CacheConfiguration("defaultCache", 100))
.cache(new CacheConfiguration("example", 100)
.timeToIdleSeconds(5)
.timeToLiveSeconds(120)
.terracotta(new TerracottaConfiguration()));
CacheManager manager = new CacheManager(configuration);

The above example looks for sampleTerracottaCache. In ehcache.xml, we need to uncomment or add the following line:

<terracottaConfig url="localhost:9510"/>

This tells Ehcache to load the Terracotta server config from localhost port 9510. For url configuration options, refer to "Adding an URL Attribute" in Terracotta Clustering Configuration Elements. Note: You must have a Terracotta 3.1.1 or higher server running locally for this example.

Next we want to enable Terracotta clustering for the cache named sampleTerracottaCache. Uncomment or add the following in ehcache.xml.

<cache name="sampleTerracottaCache"

maxEntriesLocalHeap="1000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="1800"

overflowToDisk="false">

<terracotta/>

</cache>

That's it!

 

更多詳細信息參見:http://ehcache.org/documentation/configuration


免責聲明!

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



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