像Hibernate這種ORM框架,相較於JDBC操做,須要有更復雜的機制來實現映射、對象狀態管理等,所以在性能和效率上有必定的損耗。html
在保證避免映射產生低效的SQL操做外,緩存是提高Hibernate的關鍵之一。java
加入緩存能夠避免數據庫調用帶來的鏈接建立與銷燬、數據打包拆包、SQL執行、網絡傳輸,良好的緩存機制和合理的緩存模式能帶來性能的極大提高,EHCache就提供了這種良好的緩存機制。數據庫
在考慮給系統加入緩存進行優化前,複用SessionFactory是Hibernate優化最優先、最基礎的性能優化方法,參考上一篇《Hibernate性能優化之SessionFactory重用》。json
Hibernate的緩存機制緩存
緩存的級別通常分爲三種,每一種緩存的範圍更大:安全
事務級緩存:Hibernate中稱爲一級緩存,在一個Session中共享緩存對象;性能優化
應用級緩存:Hibernate中稱爲二級緩存,在一個SessionFactory中共享緩存對象,SessionFactory在整個應用範圍內重用;網絡
分佈式緩存:部署爲單獨的實例,如Redis、Memcache等。多線程
Hibernate的按如下方式進行緩存:框架
當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;
查不到,若是配置了二級緩存,那麼從二級緩存中查;
若是都查不到,再查詢數據庫,把結果按照ID放入到緩存刪除、更新、增長數據的時候,同時更新緩存。
Hibernate默認不啓用二級緩存,EHCache是Hibernate中的二級緩存插件,使用Hibernate的系統能夠直接使用EHCache緩存。
爲何要直接使用EHCache
回頭來看那句話:良好的緩存機制和合理的緩存模式能帶來性能的極大提高。
Hibernate的緩存模式是什麼?
根據ID來緩存對象,也就是Session的get、load操做時。
這種緩存模式的弊端有兩點:
一、應用場景太單一,系統中大量的列表式查詢緩存起不到做用;
二、一些系統中經過ThreadLocal在線程中重用Session,每一個線程可能須要大量處理不用的業務邏輯,緩存命中率很低;若是不重用Session,通常的場景緩存命中率更低。
既然EHCache已經提供了良好的緩存機制,結合本身系統的業務來優化緩存模式纔是最佳的。
如何使用EHCache
EHCache是Hibernate中的二級緩存插件,使用Hibernate的系統能夠直接使用EHCache緩存,不須要再添加其餘jar包。
新建EHCache配置文件,具體的配置含義能夠查手冊:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" maxElementsOnDisk="0" eternal="true" overflowToDisk="true" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="0" diskSpoolBufferSizeMB="50" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LFU" /> <cache name="restCache" maxElementsInMemory="100" maxElementsOnDisk="0" eternal="false" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="119" timeToLiveSeconds="119" diskSpoolBufferSizeMB="50" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="FIFO" /> </ehcache>
EHCache的一個優勢是線程安全的,適合多線程的使用場景,能簡化開發人員的使用。
所以我寫了一個單例模式,避免每次在方法裏寫getCache,這個類也涵蓋了EHCache的基本使用:
public class EHCacheFactory { private final CacheManager manager; private final Cache cache; private EHCacheFactory() { manager = CacheManager.create(getClass().getResource("/ehcache.xml")); cache = manager.getCache("restCache"); } public Element getCache(String strKey) { return EHCacheFactory.getInstance().getCache().get(strKey); } public void setCache(String strKey, String strVal) { EHCacheFactory.getInstance().getCache().put(new Element(strKey, strVal)); } public Cache getCache() { return cache; } private static class SingletonHolder { private final static EHCacheFactory INSTANCE = new EHCacheFactory(); } public static EHCacheFactory getInstance() { return SingletonHolder.INSTANCE; } }
個人系統是JAVA REST,在須要緩衝的REST接口中加入了EHCache緩存,經過URL參數做爲緩存鍵值,REST接口返回的json數據做爲緩存值,這種緩存模式很是適合REST。
使用ab進行了簡單的性能測試:
在一個簡答查詢接口中,性能提高一倍;
在一個略複雜接口中,執行四、5個查詢,加入緩存後性能提高20倍。
在這裏就不貼ab測試結果了,你們能夠自行測試一下。
記錄,爲更好的本身!