Java分布式緩存框架Ehcache 使用(一)

  • 在開發(fā)中大型Java軟件項(xiàng)目時(shí),對(duì)于頻繁讀寫數(shù)據(jù)庫的操作,為了減輕數(shù)據(jù)庫的壓力,我們常常會(huì)用到緩存。因?yàn)閿?shù)據(jù)庫連接是非?!鞍嘿F”的資源,因此我們需要增加一個(gè)抽象層來解決,緩存層應(yīng)用而生。

  • 緩存的數(shù)據(jù)是保存在內(nèi)存中的,而內(nèi)存的速度是硬盤的10萬倍,所以讀取速度相當(dāng)快。第一次訪問從數(shù)據(jù)庫讀取數(shù)據(jù), 并且放到緩存中;后續(xù)訪問直接從緩存中讀取數(shù)據(jù);發(fā)生變化,既要更新數(shù)據(jù)庫, 也要更新緩存。

  • 說到緩存,大家可能直接印象就是Redis,方便好用。但是Redis是通過網(wǎng)絡(luò)傳輸?shù)模援?dāng)數(shù)據(jù)庫大的時(shí)候Redis的壓力就太大了,這時(shí)候我們就需要在本地內(nèi)存中建立緩存。本地緩存最簡(jiǎn)單的方式是寫一個(gè)HashMap,以key-value的形式實(shí)現(xiàn)。但是這種方式不能對(duì)緩存的有效期進(jìn)行設(shè)置,如果不手動(dòng)將map置為null,將會(huì)一直占用內(nèi)存空間。所以需要一個(gè)緩存框架來解決問題。

  • 本地的緩存框架有很多,常用的有Ehcache,Cacheonix,ASimpleCache ,JBoss Cache,Voldemort 。今天來說EHCache。

  • Ehcache是一個(gè)Java實(shí)現(xiàn)的開源分布式緩存框架,EhCache 可以有效地減輕數(shù)據(jù)庫的負(fù)載,可以讓數(shù)據(jù)保存在不同服務(wù)器的內(nèi)存中,在需要數(shù)據(jù)的時(shí)候可以快速存取。同時(shí)EhCache 擴(kuò)展非常簡(jiǎn)單,官方提供的Cache配置方式有好幾種??梢酝ㄟ^聲明配置、在xml中配置、在程序里配置或者調(diào)用構(gòu)造方法時(shí)傳入不同的參數(shù)。


    ehcache架構(gòu).png
  • Ehcache有以下特點(diǎn):

  1. 存取速度非???,性能很不錯(cuò)。
  2. 可以應(yīng)用多種緩存策略。
  3. 分級(jí)緩存,用戶可以指定哪些數(shù)據(jù)在硬盤中緩存,哪些數(shù)據(jù)在內(nèi)存中緩存。
  4. 可以通過RMI、可插入API等方式進(jìn)行分布式緩存。
  5. 具有緩存和緩存管理器的偵聽接口。
  6. 支持多緩存管理器實(shí)例,以及一個(gè)實(shí)例的多個(gè)緩存區(qū)域。
  7. 默認(rèn)提供Hibernate的緩存實(shí)現(xiàn)。
    配置有好多方式,但是萬變不離其宗,知道配置參數(shù)意義才是最重要的。
  • 在使用EHCache時(shí),需要在工程根目錄里配置ehcache.xml,如果想通過自己手動(dòng)控制緩存添加和釋放就像redis那樣操作,可以寫一個(gè)EHCacheUtil類來操作。
    ehcache.xml配置如下:
<ehcache>

    <!--<diskStore path="java.io.tmpdir"/> -->
    <diskStore path="data/ehcache" />
    <defaultCache maxElementsInMemory="10000" eternal="false"
        overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />

    <cache name="tagCache" maxElementsInMemory="10000" eternal="false"
        timeToIdleSeconds="300" timeToLiveSeconds="1800" overflowToDisk="true"
        diskPersistent="false" />

</ehcache>

配置的一些參數(shù)含義如下:

maxElementsInMemory:設(shè)置緩存中允許存放的最大條目數(shù)量
eternal:緩存內(nèi)容是否永久存儲(chǔ)在內(nèi)存;該值設(shè)置為true時(shí),timeToIdleSeconds和timeToLiveSeconds兩個(gè)屬性的值就不起作用了。
overflowToDisk:如果內(nèi)存中的數(shù)據(jù)超過maxElementsInMemory,是否使用磁盤存儲(chǔ)。
timeToLiveSeconds:緩存自創(chuàng)建日期起至失效時(shí)的間隔時(shí)間;
timeToIdleSeconds:緩存創(chuàng)建以后,最后一次訪問緩存的日期至失效之時(shí)的時(shí)間間隔;
如果僅有timeToLiveSeconds那么自創(chuàng)建時(shí)間開始 間隔x后緩存失效;
如果沒有timeToLiveSeconds那么自最后一次訪問緩存 間隔y后 緩存失效;
如果既有timeToLiveSeconds也有timeToIdleSeconds那么取最小數(shù)算作間隔時(shí)間;min(x,y);
diskPersistent:磁盤存儲(chǔ)的條目是否永久保存
diskExpiryThreadIntervalSeconds:磁盤清理線程的運(yùn)行時(shí)間間隔
注意:時(shí)間都是以秒為單位
配置完ehcache.xml之后,就可以寫一個(gè)EHCacheUtil類了:

/**
 * 對(duì)EHCache進(jìn)行了簡(jiǎn)單的封裝
 * 建議在頻繁使用且重負(fù)載的函數(shù)實(shí)現(xiàn)中使用緩存
 * Ehcache會(huì)將每個(gè)緩存配置的文件路徑下創(chuàng)建一個(gè)cache_name.data文件,如果使用的磁盤持久化技術(shù),還會(huì)生成一個(gè)cache name.index文件。
 * @author kouyy
 */
public class EHCacheUtil {

    static CacheManager manager=null;
    static String configfile="ehcache.xml";

    //EHCache初始化
    static{
        try {
            manager = CacheManager.create(EHCacheUtil.class.getClassLoader().getResourceAsStream(configfile));
        } catch (CacheException e) {
            e.printStackTrace();
        }
    }

    /**
     * 將數(shù)據(jù)存入Cache
     * @param cachename Cache名稱
     * @param key 類似redis的Key
     * @param value 類似redis的value,value可以是任何對(duì)象、數(shù)據(jù)類型,比如person,map,list等
     */
    public static void put(String cachename,Serializable key,Serializable value){
        manager.getCache(cachename).put(new Element(key, value));
    }

    /**
     * 獲取緩存cachename中key對(duì)應(yīng)的value
     * @param cachename
     * @param key
     * @return
     */
    public static Serializable get(String cachename,Serializable key){
        try {
            Element e=manager.getCache(cachename).get(key);
            if(e==null){
                return null;
            }
            return e.getValue();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (CacheException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 清除緩存名稱為cachename的緩存
     * @param cachename
     */
    public static void clearCache(String cachename){
        try {
            manager.getCache(cachename).removeAll();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 移除緩存cachename中key對(duì)應(yīng)的value
     * @param cachename
     * @param key
     */
    public static void remove(String cachename,Serializable key){
        manager.getCache(cachename).remove(key);
    }
}

實(shí)際操作很像redis,都是對(duì)key-value的操作,只是ehcache在每次操作的時(shí)候需要指明緩存的名稱,僅此而已。
在同類的Java緩存框架中,Ehcache配置相對(duì)簡(jiǎn)單,也比較容易上手,最大的優(yōu)勢(shì)是它支持分布式緩存。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容