【Mybatis】一級緩存、二級緩存介紹與常見問題(四) 轉

一般來說,可以在5個方面進行緩存的設計:

1.最底層可以配置的是mysql自帶的query cache,

2.mybatis的一級緩存,默認情況下都處於開啓狀態,只能使用自帶的PerpetualCache,無法配置第三方緩存

3.mybatis的二級緩存,可以配置開關狀態,默認使用自帶的PerpetualCache,但功能比較弱,能夠配置第三方緩存

4.service層的緩存配置,結合spring,可以靈活進行選擇

5.針對實際業務情況,直接緩存部分html頁面,直接返回給客戶端。

 

在測試過程中,發現mybatis的一級緩存沒有起作用,失效了。經過調研,發現是由於以下原因引起的:

1.mybatis的一級緩存生效的範圍是sqlsession,是爲了在sqlsession沒有關閉時,業務需要重複查詢相同數據使用的。一旦sqlsession關閉,則由這個sqlsession緩存的數據將會被清空。

2.spring對mybatis的sqlsession的使用是由template控制的,sqlsession又被spring當作resource放在當前線程的上下文裏(threadlocal),spring通過mybatis調用數據庫的過程如下:

           a.我們需要訪問數據

           b.spring檢查到了這種需求,於是去申請一個mybatis的sqlsession(資源池),並將申請到的sqlsession與當前線程綁定,放入threadlocal裏面

           c.template從threadlocal獲取到sqlsession,去執行查詢

           d.查詢結束,清空threadlocal中與當前線程綁定的sqlsession,釋放資源

           e.我們又需要訪問數據

           f.返回到步驟b

通過以上步驟後發現,同一線程裏面兩次查詢同一數據所使用的sqlsession是不相同的,所以,給人的印象就是結合spring後,mybatis的一級緩存失效了。

一級緩存,是Session級別的緩存,它會把這個操作的結果放在一級緩存中。短時間內這個session(一定要同一個session)又做了同一個操作,那麼直接從一級緩存中拿,而不會再去連數據庫,取數據。它是內置的事務範圍的緩存,不能被卸載。

二級緩存,是SessionFactory級別的緩存,查詢的時候會把查詢結果緩存到二級緩存中。 如果同一個sessionFactory創建的某個session執行了相同的操作,就會從二級緩存中拿結果,而不會再去連接數據庫。 這是可選的插件式的緩存,在默認情況下,SessionFactory不會啓用這個插件。

可以在每個類或每個集合的粒度上配置,嚴格意義上說,SessionFactory緩存分爲兩類:內置緩存和外置緩存。我們通常意義上說的二級緩存是指外置緩存。內置緩存與session級別緩存實現方式相似,前者是SessionFactory對象的一些集合屬性包含的數據,後者是指Session的一些集合屬性包含的數據。SessionFactory的內置緩存中存放了映射元數據和預定義SQL語句。

SessionFactory的內置緩存是隻讀的,應用程序不能修改緩存中的映射元數據和預定義SQL語句,因此SessionFactory不需要進行內置緩存與映射文件的同步。


Hibernate的這兩級緩存都位於持久化層,存放的都是數據庫數據的拷貝。
緩存的併發訪問策略
1、緩存的範圍
決定了緩存的生命週期以及可以被誰訪問。緩存的範圍分爲三類。
事務範圍
進程範圍
集羣範圍
注:
對大多數應用來說,應該慎重地考慮是否需要使用集羣範圍的緩存,因爲訪問的速度不一定會比直接訪問數據庫數據的速度快多少。
事務範圍的緩存是持久化層的第一級緩存,通常它是必需的;進程範圍或集羣範圍的緩存是持久化層的第二級緩存,通常是可選的。
2、緩存的併發訪問策略
當多個併發的事務同時訪問持久化層的緩存的相同數據時,會引起併發問題,必須採用必要的事務隔離措施。
在進程範圍或集羣範圍的緩存,即第二級緩存,會出現併發問題。
因此可以設定以下四種類型的併發訪問策略,每一種策略對應一種事務隔離級別。
事務型併發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,併發性能就越低。

隔離級別 髒讀 不可重複讀 幻讀
非嚴格讀寫型(TRANSACTION_READ_UNCOMMITTED) 允許 允許 允許
讀寫型(TRANSACTION_READ_COMMITTED) 不允許 允許 允許
事務型(TRANSACTION_REPEATABLE_READ) 不允許 不允許 允許
只讀型(TRANSACTION_SERIALIZABLE) 不允許 不允許 不允許


A 事務型:僅僅在受管理環境中適用( TRANSACTION_REPEATABLE_READ )。它提供了Repeatable Read事務隔離級別。
對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀和不可重複讀這類的併發問題。
B 讀寫型:提供了Read Committed事務隔離級別( TRANSACTION_READ_COMMITTED )。僅僅在非集羣的環境中適用。
對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀這類的併發問題。
C 非嚴格讀寫型:不保證緩存與數據庫中數據的一致性( TRANSACTION_READ_UNCOMMITTED )。
如果存在兩個事務同時訪問緩存中相同數據的可能,必須爲該數據配置一個很短的數據過期時間,從而儘量避免髒讀。
對於極少被修改,並且允許偶爾髒讀的數據,可以採用這種併發訪問策略。
D 只讀型:對於從來不會修改的數據,如參考數據,可以使用這種併發訪問策略( TRANSACTION_SERIALIZABLE )。
除此之外,還有 TRANSACTION_NONE  不使用事務。


什麼樣的數據適合存放到第二級緩存中?
1、很少被修改的數據
2、不是很重要的數據,允許出現偶爾併發的數據
3、不會被併發訪問的數據
4、參考數據


不適合存放到第二級緩存的數據?
1、經常被修改的數據
2、財務數據,絕對不允許出現併發
3、與其他應用共享的數據


Hibernate的二級緩存策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。
2) 把獲得的所有數據對象根據ID放入到第二級緩存中。
3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那麼從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。
4) 刪除、更新、增加數據的時候,同時更新緩存。
注:
Hibernate的二級緩存策略,是針對於ID查詢的緩存策略,對於條件查詢則毫無作用。爲此,Hibernate提供了針對條件查詢的Query緩存。
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都要從緩存中清空。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章