深入理解 MyBatis的二級快取的設計原理

weixin_34054866發表於2018-12-05

點選關注,快速進階高階架構師

作者:亦山

MyBatis的二級快取是Application級別的快取,它可以提高對資料庫查詢的效率,以提高應用的效能。本文將全面分析MyBatis的二級快取的設計原理。

MyBatis的快取機制整體設計以及二級快取的工作模式

深入理解 MyBatis的二級快取的設計原理

如上圖所示,當開一個會話時,一個SqlSession物件會使用一個Executor物件來完成會話操作,MyBatis的二級快取機制的關鍵就是對這個Executor物件做文章。如果使用者配置了"cacheEnabled=true",那麼MyBatis在為SqlSession物件建立Executor物件時,會對Executor物件加上一個裝飾者:CachingExecutor,這時SqlSession使用CachingExecutor物件來完成操作請求。CachingExecutor對於查詢請求,會先判斷該查詢請求在Application級別的二級快取中是否有快取結果,如果有查詢結果,則直接返回快取結果;如果快取中沒有,再交給真正的Executor物件來完成查詢操作,之後CachingExecutor會將真正Executor返回的查詢結果放置到快取中,然後在返回給使用者。

深入理解 MyBatis的二級快取的設計原理

CachingExecutor是Executor的裝飾者,以增強Executor的功能,使其具有快取查詢的功能,這裡用到了設計模式中的裝飾者模式,

CachingExecutor和Executor的介面的關係如下類圖所示:

深入理解 MyBatis的二級快取的設計原理

MyBatis二級快取的劃分

MyBatis並不是簡單地對整個Application就只有一個Cache快取物件,它將快取劃分的更細,即是Mapper級別的,即每一個Mapper都可以擁有一個Cache物件,具體如下:

a.為每一個Mapper分配一個Cache快取物件(使用<cache>節點配置);

b.多個Mapper共用一個Cache快取物件(使用<cache-ref>節點配置);

如果你想讓多個Mapper公用一個Cache的話,你可以使用<cache-ref namespace="">節點,來指定你的這個Mapper使用到了哪一個Mapper的Cache快取。

深入理解 MyBatis的二級快取的設計原理

使用二級快取,必須要具備的條件

MyBatis對二級快取的支援粒度很細,它會指定某一條查詢語句是否使用二級快取。

雖然在Mapper中配置了<cache>,並且為此Mapper分配了Cache物件,這並不表示我們使用Mapper中定義的查詢語句查到的結果都會放置到Cache物件之中,我們必須指定Mapper中的某條選擇語句是否支援快取,即如下所示,在<select> 節點中配置useCache="true",Mapper才會對此Select的查詢支援快取特性,否則,不會對此Select查詢,不會經過Cache快取。如下所示,Select語句配置了useCache="true",則表明這條Select語句的查詢會使用二級快取。

 <select id="selectByMinSalary" resultMap="BaseResultMap" parameterType="java.util.Map" useCache="true">

總之,要想使某條Select查詢支援二級快取,你需要保證:

1. MyBatis支援二級快取的總開關:全域性配置變數引數 cacheEnabled=true

2. 該select語句所在的Mapper,配置了<cache> 或<cached-ref>節點,並且有效

3. 該select語句的引數 useCache=true

一級快取和二級快取的使用順序

請注意,如果你的MyBatis使用了二級快取,並且你的Mapper和select語句也配置使用了二級快取,那麼在執行select查詢的時候,MyBatis會先從二級快取中取輸入,其次才是一級快取,即MyBatis查詢資料的順序是:

二級快取 ———> 一級快取——> 資料庫

二級快取實現的選擇

MyBatis對二級快取的設計非常靈活,它自己內部實現了一系列的Cache快取實現類,並提供了各種快取重新整理策略如LRU,FIFO等等;另外,MyBatis還允許使用者自定義Cache介面實現,使用者是需要實現org.apache.ibatis.cache.Cache介面,然後將Cache實現類配置在<cache type="">節點的type屬性上即可;除此之外,MyBatis還支援跟第三方記憶體快取庫如Memecached的整合,總之,使用MyBatis的二級快取有三個選擇:

1.MyBatis自身提供的快取實現;

2. 使用者自定義的Cache介面實現;

3.跟第三方記憶體快取庫的整合;

MyBatis自身提供的二級快取的實現

MyBatis自身提供了豐富的,並且功能強大的二級快取的實現,它擁有一系列的Cache介面裝飾者,可以滿足各種對快取操作和更新的策略。

MyBatis定義了大量的Cache的裝飾器來增強Cache快取的功能,如下類圖所示。

對於每個Cache而言,都有一個容量限制,MyBatis各供了各種策略來對Cache快取的容量進行控制,以及對Cache中的資料進行重新整理和置換。MyBatis主要提供了以下幾個重新整理和置換策略:

LRU:(Least Recently Used),最近最少使用演算法,即如果快取中容量已經滿了,會將快取中最近做少被使用的快取記錄清除掉,然後新增新的記錄;

FIFO:(First in first out),先進先出演算法,如果快取中的容量已經滿了,那麼會將最先進入快取中的資料清除掉;

Scheduled:指定時間間隔清空演算法,該演算法會以指定的某一個時間間隔將Cache快取中的資料清空;

深入理解 MyBatis的二級快取的設計原理

6. 寫在後面(關於涉及到的設計模式)

在二級快取的設計上,MyBatis大量地運用了裝飾者模式,如CachingExecutor, 以及各種Cache介面的裝飾器。

本文只是講述MyBatis二級快取的基本原理,關於自定義二級快取和與第三方記憶體庫的整合,將在後續的文章中再做討論,敬請關注!

https://blog.csdn.net/luanlouis/article/details/41408341

相關文章