Hibernate的cache管理

來源:互聯網
上載者:User
Cache就是緩衝,它往往是提高系統效能的最重要手段,對資料起到一個蓄水池和緩衝的作用。Cache對於大量依賴資料讀取操作的系統而言尤其重要。在大並發量的情況下,如果每次程式都需要向資料庫直接做查詢操作,它們所帶來的效能開銷是顯而易見的,頻繁的網路輿,資料庫磁碟的讀寫操作都會大大降低系統的效能。此時如果能讓資料庫在本地記憶體中保留一個鏡像,下次訪問的時候只需要從記憶體中直接擷取,那麼顯然可以帶來不小的效能提升。引入Cache機制的痛點是如何保證記憶體中資料的有效性,否則髒資料的出現將會給系統帶來難以預知的嚴重後果。雖然一個設計得很好的應用程式不用Cache也可以表現出讓人接受的效能,但毫無疑問,一些對讀取操作要求比較高的應用程式可以通過Cache獲得更高的效能。對於應用程式,Cache通過記憶體或磁碟儲存了資料庫中的當前有關資料狀態,它是一個儲存在本地的資料備份。Cache位於資料庫和應用程式之間,從資料庫更新資料,並給程式提供資料。
Hibernate實現了良好的Cache機制,可以藉助Hibernate內部的Cache迅速提高系統的資料讀取效能。Hibernate中的Cache可分為兩層:一級Cache和二級Cache。
一級Cache:
Session實現了第一級Cache,它屬於事務級資料緩衝。一旦事務結束,這個Cache也隨之失效。一個Session的生命週期對應一個資料庫事務或一個程式事務。
Session-cache保證了一個Session中兩次請求同一個對象時,取得的對象是同一個JAVA執行個體,有時它可以避免不必要的資料衝突。另外,它還能為另一些重要的效能提供保證:
1:在對一個對象進行自我循環參考時, 不至於產生堆疊溢位。
2:當資料庫事務結束時,對於同一個資料庫行,不會產生資料衝突,因為對於資料庫中的一行,最多隻有一個對象來表示它。
3:一個事務中可能會有很多個處理單元,在每一個處理單元中做的操作都會立即被另外的處理單元得知。
我們不用刻意去開啟Session-cache,它總是被開啟並且不能被關閉。當使用save(),update()或saveOrUpdate()來儲存資料更改,或通過load(),find(),list()等方法來得到對象時,對象就會被加入到Session-cache。
如果要同步很多資料對象,就需要有效地管理Cache,可以用Session的evict()方法從一級Cache中移除對象。如下:

Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
for(int i = 0 ; i <100000 ; i++)
{
    Student stu = new Student();
    
    session.save(stu);
}
tx.commit();
session.close();

在儲存50000個或更多個物件時,程式可能會拋出OutOfMemoryException異常,因為Hibernate在一級Cache緩衝了新加入的所有對象。記憶體溢出。要解決這全問題就需要把JDBC批處理數量設定為一個合理的數值(一般是10~20)。在Hibernate的設定檔中可以加入以下屬性<property name="hibernate.jdbc.batch_size"> 20 </property>

然後我們在程式中一定時刻就提交並更新Session的Cache:

Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
for(int i = 0 ; i <100000 ; i++)
{
    Student stu = new Student();
    
    session.save(stu);
    if(i%20 == 0)    //每儲存完20個對象後,進行如下操作
    {
        session.flush();//這個會提交更新
        session.clear();//清除Cache,釋放記憶體
    }
}
tx.commit();
session.close();

二級Cache
二級Cache是SessionFactory範圍內的緩衝,所有的Session共用同一個二級Cache。在二級Cache中儲存持久性執行個體的散裝形式的資料。二級Cache的內部如何?並不重要,重要的是採用哪種正確的緩衝策略,以及採用哪個Cache提供器。持久化不同的資料需要不同的Cache策略,比如一些因素將影響到Cache策略的選擇:資料的讀/寫比例,資料表是否能被其他的應用程式揚訪問等。對於一些讀/寫比例高的資料可以開啟它的緩衝,允許這些資料進入二級緩衝容器有利於系統效能的最佳化;而對於能被其它應用程式訪問的資料對象,最好將此對象的二級Cache選項關閉。
設定Hibernate的二級Cache需要分兩步進行:首先確認使用什麼資料並發策略,然後配置緩衝到期時間並設定Cache提供器。
有4種內建的Hibernate資料並發衝突策略,代表資料庫隔離等級,如下:
1:事務(Transaction)僅在受管理的環境中可用。它保證可重讀的交易隔離等級,可以對讀/寫比例高,很少更新的資料採用該策略。
2:讀寫(read-write)使用時間戳機制維護讀寫提交交易隔離等級。可以對讀/寫比例高,很少更新的資料採用該策略。
3:非嚴格讀寫(notstrict-read-write)不保證Cache和資料庫之間的資料庫的一致性。使用此策略時,應該設定足夠的緩衝到期時間,否則可能從緩衝中讀出髒資料。當一些資料極少改變,並且當這些資料和資料庫有一部份不量影響不大時,可以使用此策略。
4:唯讀(read-only)當確保資料永不改變時,可以使用此策略。

我們確定了Cache策略後,就要挑選一個高效的Cache提供器,它將作為外掛程式被Hibernate調用。Hibernate允許使用下述幾種快取區外掛程式:
EhCache:可以在JVM中作為一個簡單進程範圍內的緩衝,它可以把緩衝的資料放入記憶體或磁碟,並支援Hibernate中可選用的查詢快取。
OpenSymphony OSCache:和EhCache相似,並且提供了豐富的緩衝到期策略。
SwarmCache:可作為叢集範圍的緩衝,但不支援查詢快取。
JBossCache:可作為叢集範圍的緩衝,但不支援查詢快取。

在Hibernate中使用EhCache
EhCache是一個純JAVA程式,可以在Hibernate中作為一個外掛程式引入。在Hibernate中使用EhCache需要在Hibernate的設定檔中設定如下:

<propery name="hibernate.cache.provider_class">
    org.hibernate.cache.EhCacheProvider
</property>

EhCacheProvider類是位於Hibernate3.jar包中而不是ehcache-1.1.jar包中。EhCache有自己的配置文檔,名為chcache.xml。Hibernate3.x中的etc目錄下有ehcache.xml的樣本檔案,只須要將 它COPY到我們的應用程式src目錄下(編譯時間會把ehcache.xmlCOPY到WEB-INF/classes目錄下)。對其中的相關值變更以和自己的程式相適應。進行配置後,在ehcache.xml檔案中的代碼如下:

<ehcache>
    <diskStore path="c:\\cache"/>    //設定cache.data檔案存放位置

    <defaultCache
                maxElementsInMemory="10000" //緩衝中允許建立的最大對象數
                eternal="false"    //緩衝中對象是否為永久的
                timeToIdleSeconds="120"//快取資料鈍化時間(即對象在它到期前的空閑時間)
                timeToLiveSeconds="120"//快取資料存留時間(即對象在它到期前的存留時間)
                overflowToDisk="true"
    />
    
    <cache name="Student"    //使用者自訂的Cache配置
                 maxElementsInMemory="10000"
                 eternal="false"
                 timeToIdleSeconds="300"
                 timeToLiveSeconds="600"
                 overflowToDisk="true"
                 />
</ehcache>

此外我們還需要在持久化類的對應檔中進行配置。例如,Group(班級)和Student(學生)是一對多的關係,它們對應的資料表分別是t_group和t_student。現在要把Student類的資料進行二級緩衝,這需要在二個對應檔中都對二級緩衝進行配置。
在Group.hbm.xml中如下
在其<set></set>中添加

<cache usage="read-write"/><!--集合中的資料被緩衝-->

上述檔案雖然在<set>標記中設定了<cache usage="read-write"/>,但Hibernate只是把Group相關的Student的主鍵ID加入到緩衝中,如果希望把整個Student的散裝屬性都加入到二級緩衝中,還需要在Student.hbm.xml檔案的<class>標記中添加<cache>子標記。如下:

<class name="Student" table="t_student">
    <cache usage="read-write" /><!--cache標記需跟在class標記後-->
</class>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.