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