使用EHCache需要注意的幾個問題


最近做一個小項目,需要對一批數據進行緩存,且要求持久化到磁盤。使用ehcache非常簡單和直觀,一般來說只需要配置ehcache.xml文件,接着直接使用@Cacheable, @Cacheput, @CacheEvict即可。

三個注解的意思也很簡單,這里就不說了。

 

ehchche.xml的配置非常簡單和直觀:

<!--name:緩存名稱-->
    <!--maxElementsInMemory:緩存最大個數-->
    <!--eternal:緩存中對象是否為永久的,如果是,超時設置將被忽略,對象從不過期-->
    <!--timeToIdleSeconds:置對象在失效前的允許閑置時間(單位:秒),僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大-->
    <!--timeToLiveSeconds:緩存數據的生存時間(TTL),也就是一個元素從構建到消亡的最大時間間隔值,這只能在元素不是永久駐留時有效,如果該值是0就意味着元素可以停頓無窮長的時間-->
    <!--overflowToDisk:內存不足時,是否啟用磁盤緩存-->
    <!--maxElementsOnDisk:設置成0 表示硬盤中最大緩存對象數無限大-->
    <!--diskPersistent:設置成true表示緩存虛擬機重啟期數據磁盤存儲是否在虛擬機重啟后持續存在-->
    <cache name="appdsCache"
           maxElementsInMemory="0"
           eternal="true"
           maxElementsOnDisk="10000000"
           overflowToDisk="true"
           diskPersistent="true"
           memoryStoreEvictionPolicy="LRU">
        <!--<persistence strategy="localRestartable" synchronousWrites="false"/>-->
    </cache>

 

但是在使用過程中遇到了兩個小問題,下面簡單的做個記錄。

1. 在類中寫了一個帶有緩存注解的方法,然后在一個普通方法中調用了這個緩存函數,則緩存功能不再生效。如下:

@EnableCaching
class
A implements IA{ public String funA(){ return funB(); } @Cacheable public String funB(){ ... } }

其實這和Spring的對象注入機制有關,例如,當外部通過@Autowired注解得到一個A類的對象時,其實得到的是一個spring包裝過的代理對象。

 

當調用a.funB()時,實際調用的是spring的proxy對象中的funB()方法,該方法內置了cache機制,在cache檢查后就會調用實際的a對象中的funA方法。

 

同理當調用a.funA()時,也是先調用spring的proxy對象中的funA()方法,經過檢查和資源分配等步驟后,會調用實際的a對象中的funA()方法,但是當在實際的A類對象中再調用funB()時,不會觸發cache機制,因為此時調用的不是SpringCacheProxy對象,而是一個實際的A類對象,所以不會觸發cache機制。

 

如果深入研究Spring完成注入和AOP編程實現的原理,可以發現動態代理是很重要的一個技術。目前Spring的動態代理主要是通過CGLib來實現的。

 

那么這個問題如何解決呢?有兩種思路:

(1) 拆分為兩個類來實現。即將funA()和funB()寫在兩個類中。

(2) 在類中注入自身實例。如下:

@EnableCaching
@Service(value="a") class A implements IA{
@Resource(name
="a") private IA a; public String funA(){ return a.funB(); } @Cacheable public String funB(){ ... }
}

第二種方法親測有效~~

不管怎樣,都要記住如下原則:同一個類中的注解方法互相調用時,注解機制可能是無效的。

 

2. (在idea中點擊紅色按鈕關閉程序時) 持久化到磁盤的數據無法恢復。

原因如下:ehcache和其它緩存類似,需要flush或shutdown后才會持久化到磁盤

     會生成.data 的數據文件和 .index 的索引文件,方便重啟恢復。

       ehcache恢復數據是根據.index索引文件來進行數據恢復的。

       當程序再次啟動的時候,ehcache的一個方法會將.data文件和.index文件的修改時間進行比較,如果不符合直接將.index文件刪除。

 

一般來說,以下兩種情況,會自動調用shutdown()函數:

(1) 調用System.exit(),或最后一個非守護線程退出。

(2) 虛擬機停止運行。例如在命令行中執行CTRL+C,這會導致kill -SIGTERM pid 或kill -15 pid。

 

而在idea中點擊紅色按鈕時,屬於非正常關閉,導致shutdown()未能執行,猜測執行的是類似kill-9直接殺死進程的方法,而不是kill-15比較安全的關閉。

 

官網建議是最好是在程序關閉之前顯式地調用shutdown()函數,但是實際實踐中,就算是顯式調用了shutdown(),要是在程序運行到一半時點擊idea的紅色關閉按鈕,緩存還是會失效。。

在我看來最安全的方法就是把程序打成jar包運行,用CTRL+C在命令行終止程序,就算此時程序並沒有執行完,shutdown()也會執行。


免責聲明!

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



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