MyBatis驗證多級緩存及 Cache Aside 模式的應(yīng)用小結(jié)
前言
MyBatis 官方文檔 中文版本沒有翻譯cache的部分,網(wǎng)上資料比較雜。
這里使用 Spock 測試框架驗證下多級緩存,并探索 Mybatis 的 CacheAside 模式。注意:
- 本文用 本地緩存 表示一級緩存,全局緩存 表示二級緩存
- 用例倉庫
1. 多級緩存的概念
多級緩存可以聯(lián)系CPU的結(jié)構(gòu),離核心約近的一致性越高。
1.1 CPU 多級緩存
1.2 MyBatis 多級緩存
本地緩存默認開啟,全局緩存需要使用 <cache/>
開啟
By default, just local session caching is enabled that is used solely to cache data for the duration of a session. To enable a global second level of caching you simply need to add one line to your SQL Mapping file:
<mapper namespace="com.james.mapper.FileCacheMapper"> <cache/> <!-- 聲明該標簽,全局緩存開啟 --> <select id="select" resultType="java.lang.String"> SELECT file_name FROM file </select> </mapper>
2. MyBatis 本地緩存
用 Spring 注入的 mapper,調(diào)用一次select方法就會產(chǎn)生一個 sqlSession,沒有利用到本地緩存。
def "未使用事務(wù),第二次查詢,不命中本地緩存"() { given: def list1 = mapper.select() def list2 = mapper.select() expect: list1 !== list2 }
用事務(wù)包裹后,兩次 select 共用一個 sqlSession,緩存命中
def "使用事務(wù),命中緩存"() { given: def list1 = [] def list2 = [] when: transaction.execute { list1 = mapper.select() list2 = mapper.select() } then: // 同一個事務(wù)使用同一個SqlSession,若引用相同則認為命中緩存 list1 === list2 }
note: groovy 中
list1 === list2
表示引用相同,list1 == list2
表示兩個列表的內(nèi)容相同
3. MyBatis 全局緩存
上文說到,沒有事務(wù)保護的 select方法調(diào)用無法公用一個 sqlSession,所以利用不了本地緩存。
全局緩存的范圍更大,只要是同一個mapper的調(diào)用,都會被緩存。
def "全局緩存默認關(guān)閉,需要在xml文件中使用 <cache/> 標簽啟用"() { given: def list1 = fileCacheMapper.select() def list2 = fileCacheMapper.select() expect: // 由于 SerializedCache.java:64 使用的是由byte[]序列化方式存儲元素,所以實例的地址必然不同 list1 !== list2 list1 == list2 }
3.1 MyBatis 全局緩存過期算法
值得關(guān)注的是 SOFT 和 WEAK 的類型,對應(yīng)Java中軟引用和弱引用。
軟引用是在內(nèi)存不足時GC可以回收,弱引用是下次GC即可回收(比軟引用)積極。
3.2 CacheAside 模式
以下是 Mybatis 默認的全局緩存失效模式,也就是 Cache Aside 模式的應(yīng)用。
- 查詢的時候,如果沒有緩存,則寫入。
- 任何數(shù)據(jù)操作,使緩存失效。
<select ... flushCache="false" useCache="true"/> <insert ... flushCache="true"/> <update ... flushCache="true"/> <delete ... flushCache="true"/>
后記
Cache Aside 并不能保證強一致性,不然也就不會有 Paxos 這種復雜的共識算法了。 —— 《鳳凰架構(gòu)》
MyBatis 提供了緩存切口, 采用 Redis 會引入什么問題?
- 多實例之間緩存重復的失效問題,查詢時競爭寫緩存的問題。
- ORM框架與中間件耦合,違反單一職責。
萬一遇到需強一致場景,如何增強?
兩個查詢請求同時到來,此時緩存為空,需要將MySql數(shù)據(jù)寫入緩存。此時會出現(xiàn)競爭寫緩存的情況。用寫鎖來保證緩存內(nèi)的數(shù)據(jù)跟數(shù)據(jù)庫保持一致。
public void query() { if (cache 命中) { retrun cache } 獲取緩存寫鎖 if (獲取鎖失敗) { return 查數(shù)據(jù)庫 } 查數(shù)據(jù)庫 寫緩存 釋放緩存寫鎖 }
到此這篇關(guān)于MyBatis驗證多級緩存及 Cache Aside 模式的應(yīng)用小結(jié)的文章就介紹到這了,更多相關(guān)MyBatis驗證多級緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Calendar類常用示例_動力節(jié)點Java學院整理
從JDK1.1版本開始,在處理日期和時間時,系統(tǒng)推薦使用Calendar類進行實現(xiàn)。接下來通過實例代碼給大家詳細介紹Java Calendar類相關(guān)知識,需要的朋友參考下吧2017-04-04Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法
平時對接口時,經(jīng)常遇到j(luò)son字符串和map對象之間的交互,這篇文章主要給大家介紹了關(guān)于Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-07-07Spring實現(xiàn)Logback日志模板設(shè)置動態(tài)參數(shù)功能
本文介紹如何在Spring應(yīng)用中實現(xiàn)Logback日志模板的動態(tài)參數(shù)設(shè)置,通過設(shè)計traceId鏈路標識,將其動態(tài)添加到日志輸出中,從而實現(xiàn)簡易的鏈路追蹤功能,感興趣的朋友跟隨小編一起看看吧2024-11-11Springmvc conver實現(xiàn)原理及用法解析
這篇文章主要介紹了Springmvc conver實現(xiàn)原理及用法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10