緩存的介質(zhì)一般是內存,所以讀寫(xiě)速度很快。但如果緩存中存放的數據量非常大時(shí),也會(huì )用硬盤(pán)作為緩存介質(zhì)。緩存的實(shí)現不僅僅要考慮存儲的介質(zhì),還要考慮到管理緩存的并發(fā)訪(fǎng)問(wèn)和緩存數據的生命周期。
Hibernate的緩存包括Session的緩存和SessionFactory的緩存,其中SessionFactory的緩存又可以分為兩類(lèi):內置緩存和外置緩存。Session的緩存是內置的,不能被卸載,也被稱(chēng)為Hibernate的第一級緩存。SessionFactory的內置緩存和Session的緩存在實(shí)現方式上比較相似,前者是SessionFactory對象的一些集合屬性包含的數據,后者是指Session的一些集合屬性包含的數據。SessionFactory的內置緩存中存放了映射元數據和預定義SQL語(yǔ)句,映射元數據是映射文件中數據的拷貝,而預定義SQL語(yǔ)句是在Hibernate初始化階段根據映射元數據推導出來(lái),SessionFactory的內置緩存是只讀的,應用程序不能修改緩存中的映射元數據和預定義SQL語(yǔ)句,因此SessionFactory不需要進(jìn)行內置緩存與映射文件的同步。SessionFactory的外置緩存是一個(gè)可配置的插件。在默認情況下,SessionFactory不會(huì )啟用這個(gè)插件。外置緩存的數據是數據庫數據的拷貝,外置緩存的介質(zhì)可以是內存或者硬盤(pán)。SessionFactory的外置緩存也被稱(chēng)為Hibernate的第二級緩存。
Hibernate的這兩級緩存都位于持久化層,存放的都是數據庫數據的拷貝,那么它們之間的區別是什么呢?為了理解二者的區別,需要深入理解持久化層的緩存的兩個(gè)特性:緩存的范圍和緩存的并發(fā)訪(fǎng)問(wèn)策略。
持久化層的緩存的范圍
緩存的范圍決定了緩存的生命周期以及可以被誰(shuí)訪(fǎng)問(wèn)。緩存的范圍分為三類(lèi)。
1 事務(wù)范圍:緩存只能被當前事務(wù)訪(fǎng)問(wèn)。緩存的生命周期依賴(lài)于事務(wù)的生命周期,當事務(wù)結束時(shí),緩存也就結束生命周期。在此范圍下,緩存的介質(zhì)是內存。事務(wù)可以是數據庫事務(wù)或者應用事務(wù),每個(gè)事務(wù)都有獨自的緩存,緩存內的數據通常采用相互關(guān)聯(lián)的的對象形式。
2 進(jìn)程范圍:緩存被進(jìn)程內的所有事務(wù)共享。這些事務(wù)有可能是并發(fā)訪(fǎng)問(wèn)緩存,因此必須對緩存采取必要的事務(wù)隔離機制。緩存的生命周期依賴(lài)于進(jìn)程的生命周期,進(jìn)程結束時(shí),緩存也就結束了生命周期。進(jìn)程范圍的緩存可能會(huì )存放大量的數據,所以存放的介質(zhì)可以是內存或硬盤(pán)。緩存內的數據既可以是相互關(guān)聯(lián)的對象形式也可以是對象的松散數據形式。松散的對象數據形式有點(diǎn)類(lèi)似于對象的序列化數據,但是對象分解為松散的算法比對象序列化的算法要求更快。
3 集群范圍:在集群環(huán)境中,緩存被一個(gè)機器或者多個(gè)機器的進(jìn)程共享。緩存中的數據被復制到集群環(huán)境中的每個(gè)進(jìn)程節點(diǎn),進(jìn)程間通過(guò)遠程通信來(lái)保證緩存中的數據的一致性,緩存中的數據通常采用對象的松散數據形式。
對大多數應用來(lái)說(shuō),應該慎重地考慮是否需要使用集群范圍的緩存,因為訪(fǎng)問(wèn)的速度不一定會(huì )比直接訪(fǎng)問(wèn)數據庫數據的速度快多少。
持久化層可以提供多種范圍的緩存。如果在事務(wù)范圍的緩存中沒(méi)有查到相應的數據,還可以到進(jìn)程范圍或集群范圍的緩存內查詢(xún),如果還是沒(méi)有查到,那么只有到數據庫中查詢(xún)。事務(wù)范圍的緩存是持久化層的第一級緩存,通常它是必需的;進(jìn)程范圍或集群范圍的緩存是持久化層的第二級緩存,通常是可選的。
持久化層的緩存的并發(fā)訪(fǎng)問(wèn)策略
當多個(gè)并發(fā)的事務(wù)同時(shí)訪(fǎng)問(wèn)持久化層的緩存的相同數據時(shí),會(huì )引起并發(fā)問(wèn)題,必須采用必要的事務(wù)隔離措施。
在進(jìn)程范圍或集群范圍的緩存,即第二級緩存,會(huì )出現并發(fā)問(wèn)題。因此可以設定以下四種類(lèi)型的并發(fā)訪(fǎng)問(wèn)策略,每一種策略對應一種事務(wù)隔離級別。
事務(wù)型:僅僅在受管理環(huán)境中適用。它提供了Repeatable Read事務(wù)隔離級別。對于經(jīng)常被讀但很少修改的數據,可以采用這種隔離類(lèi)型,因為它可以防止臟讀和不可重復讀這類(lèi)的并發(fā)問(wèn)題。
讀寫(xiě)型:提供了Read Committed事務(wù)隔離級別。僅僅在非集群的環(huán)境中適用。對于經(jīng)常被讀但很少修改的數據,可以采用這種隔離類(lèi)型,因為它可以防止臟讀這類(lèi)的并發(fā)問(wèn)題。
非嚴格讀寫(xiě)型:不保證緩存與數據庫中數據的一致性。如果存在兩個(gè)事務(wù)同時(shí)訪(fǎng)問(wèn)緩存中相同數據的可能,必須為該數據配置一個(gè)很短的數據過(guò)期時(shí)間,從而盡量避免臟讀。對于極少被修改,并且允許偶爾臟讀的數據,可以采用這種并發(fā)訪(fǎng)問(wèn)策略。
只讀型:對于從來(lái)不會(huì )修改的數據,如參考數據,可以使用這種并發(fā)訪(fǎng)問(wèn)策略。
事務(wù)型并發(fā)訪(fǎng)問(wèn)策略是事務(wù)隔離級別最高,只讀型的隔離級別最低。事務(wù)隔離級別越高,并發(fā)性能就越低。
什么樣的數據適合存放到第二級緩存中?
1 很少被修改的數據
2 不是很重要的數據,允許出現偶爾并發(fā)的數據
3 不會(huì )被并發(fā)訪(fǎng)問(wèn)的數據
4 參考數據
不適合存放到第二級緩存的數據?
1 經(jīng)常被修改的數據
2 財務(wù)數據,絕對不允許出現并發(fā)
3 與其他應用共享的數據。
Hibernate的二級緩存
如前所述,Hibernate提供了兩級緩存,第一級是Session的緩存。由于Session對象的生命周期通常對應一個(gè)數據庫事務(wù)或者一個(gè)應用事務(wù),因此它的緩存是事務(wù)范圍的緩存。第一級緩存是必需的,不允許而且事實(shí)上也無(wú)法比卸除。在第一級緩存中,持久化類(lèi)的每個(gè)實(shí)例都具有唯一的OID。
第二級緩存是一個(gè)可插拔的的緩存插件,它是由SessionFactory負責管理。由于SessionFactory對象的生命周期和應用程序的整個(gè)過(guò)程對應,因此第二級緩存是進(jìn)程范圍或者集群范圍的緩存。這個(gè)緩存中存放的對象的松散數據。第二級對象有可能出現并發(fā)問(wèn)題,因此需要采用適當的并發(fā)訪(fǎng)問(wèn)策略,該策略為被緩存的數據提供了事務(wù)隔離級別。緩存適配器用于把具體的緩存實(shí)現軟件與Hibernate集成。第二級緩存是可選的,可以在每個(gè)類(lèi)或每個(gè)集合的粒度上配置第二級緩存。
Hibernate的二級緩存策略的一般過(guò)程如下:
1) 條件查詢(xún)的時(shí)候,總是發(fā)出一條select * from table_name where …. (選擇所有字段)這樣的SQL語(yǔ)句查詢(xún)數據庫,一次獲得所有的數據對象。
2) 把獲得的所有數據對象根據ID放入到第二級緩存中。
3) 當Hibernate根據ID訪(fǎng)問(wèn)數據對象的時(shí)候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢(xún)數據庫,把結果按照ID放入到緩存。
4) 刪除、更新、增加數據的時(shí)候,同時(shí)更新緩存。
Hibernate的二級緩存策略,是針對于ID查詢(xún)的緩存策略,對于條件查詢(xún)則毫無(wú)作用。為此,Hibernate提供了針對條件查詢(xún)的Query緩存。
Hibernate的Query緩存策略的過(guò)程如下:
1) Hibernate首先根據這些信息組成一個(gè)Query Key,Query Key包括條件查詢(xún)的請求一般信息:SQL, SQL需要的參數,記錄范圍(起始位置rowStart,最大記錄個(gè)數maxRows),等。
2) Hibernate根據這個(gè)Query Key到Query緩存中查找對應的結果列表。如果存在,那么返回這個(gè)結果列表;如果不存在,查詢(xún)數據庫,獲取結果列表,把整個(gè)結果列表根據Query Key放入到Query緩存中。
3) Query Key中的SQL涉及到一些表名,如果這些表的任何數據發(fā)生修改、刪除、增加等操作,這些相關(guān)的Query Key都要從緩存中清空。
聯(lián)系客服