Mybatis源碼之緩存模塊分析

緩存這個東西在很多應用中都能看到它們的身影,這次就講講在Mybatis中的緩存是怎么應用的,雖然說吧Mybatis中的緩存基本不怎么用,用的更多是第三方組件redis、MongoDB、MemCache等等。

Mybatis的緩存是基于Map實現的,從緩存中讀寫數據是緩存模塊的核心功能,但是除了這個功能Mybatis也提供了很多附加功能,比如防止緩存擊穿、添加緩存清空策略等等,并且這些附加的功能屬性可以隨意組合到核心功能上。

緩存在Mybatis中的使用介紹

Myabtis中有兩個緩存,一級緩存以及二級緩存,

一級緩存是默認開啟的,而二級緩存是在配置文件中開啟的,默認是開啟,但是可以配置不開啟,Mybatis配置參數定義

一級緩存的僅僅存在于同一SqlSession當中,如果關閉了SqlSession的話,那么這個緩存就沒有了,

二級緩存是跨SqlSession的存在,同一個SqlSessionFactory是有效的,在多個SqlSession當中,也會存在多個二級緩存的存在,所以就容易出現數據臟讀,個人建議二級緩存還是禁止比較好,使用第三方的緩存組件。

在對應的Mapper.xml當中使用:

eviction:使用什么類型的緩存,默認LRU緩存,緩存滿后,將使用的最少的緩存去除;

flushInterval:刷新時間;

readOnly:是否只讀;

size:緩存大小;

blocking:是否采用阻塞策略;

 <cache eviction="FIFO" flushInterval="6000" readOnly="false" size="1024"></cache>

?緩存的引用,直接引用對應的工作空間,引用后,就會直接使用這個引用的緩存:

 <cache-ref namespace="xxx.xxx.xxxDao"></cache-ref>

設計模式

先來看看這個模塊用到了哪些設計模式

裝飾器模式(Decorator Pattern)

定義:允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。

這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。

像這種組合附加功能的業務上也可以通過繼承去組合相對應的屬性,但是繼承的方式是靜態的,并不能控制增加新的屬性,如果功能屬性較多的話,那么使用繼承就會有很多子類,可讀性不強。

圖示:

組件(Component):組件接口定義了全部組件類 和裝飾器實現的行為;

組件實現類(ConcreteComponent):實現 Component接口,組件實現類就是被裝飾器裝飾的 原始對象,新功能或者附加功能都是通過裝飾器添加 到該類的對象上的;

裝飾器抽象類(Decorator):實現Component接 口的抽象類,在其中封裝了一個Component 對象, 也就是被裝飾的對象;

具體裝飾器類(ConcreteDecorator):該實現類 要向被裝飾的對象添加某些功能;

相對于繼承來說,使用裝飾器模式的靈活性更高,擴展性更強。

裝飾器使用:

JDK中的IO輸入流與輸出流設計:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("c://a.txt")));

在Servlet?API當中的對request的封裝類HttpServletRequestWrapper;

源碼分析

Mybatis的緩存模塊就是使用的裝飾器模式

BlockingCache示例:

同一個緩存的接口Cache(這個接口是緩存模塊的核心接口,定義了緩存的基本操作):

public interface Cache {/*** @return The identifier of this cache*/String getId();/*** @param key*          Can be any object but usually it is a {@link CacheKey}* @param value*          The result of a select.*/void putObject(Object key, Object value);/*** @param key*          The key* @return The object stored in the cache.*/Object getObject(Object key);/*** @param key*          The key* @return Not used*/Object removeObject(Object key);/*** Clears this cache instance.*/void clear();/*** Optional. This method is not called by the core.** @return The number of elements stored in the cache (not its capacity).*/int getSize();/*** Optional. As of 3.2.6 this method is no longer called by the core.* <p>* Any locking needed by the cache must be provided internally by the cache provider.** @return A ReadWriteLock*/default ReadWriteLock getReadWriteLock() {return null;}}

在不同屬性的實現類分別封裝一個Cache對象,實現了每個附加功能的組合。

FifoCache:一個先進先出的緩存,如果緩存的數量達到了臨界點,則將緩存時間最長的那個緩存去除。

LoggingCache:附加了日志以及統計功能。

?LruCache:如果緩存數據達到了臨界點,會將訪問次數最少的緩存數據清空。

ScheduledCache:會定時清除緩存的一個緩存。

SerializedCache:一個可以序列化以及反序列化的緩存。

SoftCache:軟引用緩存,如果緩存被GC回收后,對應的緩存數據也會被清空。

WeakCache:弱引用緩存,如果緩存被GC回收后,對應的緩存數據也會被清空。

SynchronizedCache:同步運行的緩存。

TransactionalCache:一個存在事務提交和回滾的緩存。

BlockingCache:包含阻塞機制的緩存

在緩存模塊中用到的緩存類實際上是PerpetualCache,以上的那些緩存類僅僅是附加功能,具體實現緩存功能的是PerpetualCache。

public class PerpetualCache implements Cache {private final String id;//數據被緩存的地方private final Map<Object, Object> cache = new HashMap<>();public PerpetualCache(String id) {this.id = id;}@Overridepublic String getId() {return id;}@Overridepublic int getSize() {return cache.size();}@Overridepublic void putObject(Object key, Object value) {cache.put(key, value);}@Overridepublic Object getObject(Object key) {return cache.get(key);}@Overridepublic Object removeObject(Object key) {return cache.remove(key);}@Overridepublic void clear() {cache.clear();}@Overridepublic boolean equals(Object o) {if (getId() == null) {throw new CacheException("Cache instances require an ID.");}if (this == o) {return true;}if (!(o instanceof Cache)) {return false;}Cache otherCache = (Cache) o;return getId().equals(otherCache.getId());}@Overridepublic int hashCode() {if (getId() == null) {throw new CacheException("Cache instances require an ID.");}return getId().hashCode();}}

一個比較簡單的基于Map的緩存實現類。

緩存擊穿

對于數據庫來說,緩存是一個很好的東西,它能夠擋住大部分的數據請求,但是如果在緩存中找不到對應的key和value時,那么這個這些請求就會去請求數據庫,如果這個請求是在高并發的情況或者數據是“熱數據”的情況,那么數據庫訪問那么也會變成高并發訪問查詢,這就是緩存擊穿了。

所以在設計緩存模塊的時候就應該考慮到這個問題,在Mybatis里面這個問題已經得到解決,BlockingCache就是解決方法。

我們先來看看緩存擊穿的一些解決辦法:

第一種:如果當前緩存被擊穿后,不應該讓所有的請求去請求數據庫,而是只讓一個請求去請求數據庫,其他線程等待,當數據查詢完畢并緩存進去后,再讓其他線程去查詢緩存。

但是這個方法存在一個問題,面對大量的請求來說,就會有效率問題。

第二種:既然以上方法存在效率問題,那么就可以給同等類型的key上鎖,讓相同的請求只派出一個請求去請求數據庫,其他同等類型key的請求就等待,當請求到后,那么就釋放鎖其他線程回去緩存中獲取數據了。

但是如果key太多的話,會比較浪費資源。

綜上所述:對應這種緩存的話,個人覺得應該要與業務掛鉤,取得一個平衡點取設計緩存模塊。

現在我們來看看BlockingCache是怎么玩的,其實就是給每個key上鎖然后,請求完在釋放鎖。

我目前的Mybatis版本是最新的3.5.7,可能其他版本并非使用的事CountDownLatch,而是使用的ReentrantLock,基本都是一樣,基于AQS同步,想要了解線程相關的東西,可以去看看我之前發布博客喲。

CacheKey

現在來看一下緩存的key是怎么組成的,緩存模塊中的key值并非直接的使用SQL語句中的唯一ID啥的。

在Mybatis設計緩存時,就將key包裝成一個對象,只有這個對象的hashCode相等,這兩個key才能一致。

構成CacheKey的因素有四個:

1、mappedStatment的id ;

2、指定查詢結果集的范圍(分頁信息);

3、查詢所使用的SQL語句;

4、用戶傳遞給SQL語句的實際參數值;

update方法

equals方法

Mybatis的緩存基本講的差不多了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537125.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mybatis源碼之核心流程分析

終于談到了Mybatis最核心的東西了&#xff0c;最核心的就是通過配置XML文件或注解中的SQL&#xff0c;直接調用接口就能執行配置好的SQL語句并封裝成對應的返回類型的數據。 先看一下Mybatis使用示例&#xff1a; //創建Builder對象 SqlSessionFactoryBuilder builder new S…

mimakatz用法_兩步完成利用procdump64+mimikatz獲取win用戶密碼

使用procdump64mimikatz可實現從內存中獲取明文密碼工具鏈接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密碼&#xff1a;fc38首先得先獲取到內存文件lsass.exe進程, 它用于本地安全和登陸策略,一般在進程管理器中能看到, 比如這樣1.導出lsass.exeprocdump6…

ios app提交之前需要哪幾個證書

1、遇到的問題 一款App在別人的機器上開發和發布&#xff0c;現在迭代更新和開發需要在一臺新mac機上開發和發布。&#xff08;使用同一個開發者賬號&#xff09;問題&#xff1a; 1.在新mac機器上開發并導入真機測試&#xff0c;是不是需要從別人的機器上面導處開發者證書、開…

Mybatis源碼之與Spring集成包

這次講講Mybatis與Spring的整合&#xff0c;作為兩款優秀的開源框架&#xff0c;被大眾廣泛使用&#xff0c;自然是需要強強聯合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用這兩款框架的jar包&#xff1a; <dependency>//spring-webmvc會自動去引入其他S…

hadoop主節點切換_hadoop2.0 HA的主備自動切換

在《hadoop2.0 QJM方式的HA的配置》一文中介紹了HA的配置&#xff0c;是通過手工進行主備切換的。本文在這基礎上&#xff0c;繼續介紹HA的主備自動切換(automatic failover)的配置。自動切換是通過配置zookeeper來實現的&#xff0c;關于zookeeper的安裝和配置&#xff0c;在這…

Mybatis源碼之插件模塊分析

總結完這個Mybatis的整體主要功能基本上就差不多完&#xff0c;還有一些細節的部分&#xff0c;后續都會記錄補充。 插件這個東西一般用的比較少&#xff0c;就算用的多的插件也算是PageHelper分頁插件&#xff1b; PageHelper官網&#xff1a;https://github.com/pagehelper…

AMD推出7nm高端顯卡Radeon VII,直指英偉達RTX 2080

顯卡戰爭已經發展到了2019年&#xff0c;并且變得比任何人預想的都要激烈。 CES 2019大會上&#xff0c;AMD發布了第一款消費級的 7nm GPU&#xff0c;取名&#xff1a;Radeon VII。據了解&#xff0c;這不是 AMD 的第一顆 7nm 處理器&#xff08;早期以 AI 運算為主的 Radeon …

電子繪本pdf_【孩子必看的】20本世界著名英文繪本 | PDF電子版+MP3音頻

原標題&#xff1a;【孩子必看的】20本世界著名英文繪本 | PDF電子版MP3音頻2 —6歲年齡段的孩子&#xff0c;自我意識逐漸萌芽&#xff0c;已經明白書是一種“特殊”的玩具&#xff0c;不在撕書、咬書、把書搬來搬去。這個階段他們記憶力超強&#xff0c;唐詩、三字經啥的&…

Spring集成Mybatis多數據源配置

既然在整理Mybatis那就把經常用的這個多數據源的筆記也整一下吧。 Spring集成Mybatis在之前就已經提到了。Spring集成Mybatis 集成Mybatis多數據源有兩種方式&#xff1a; 1、創建多個SqlSessionFactory&#xff0c;掃描每個SqlSessionFactoryBean對應的包&#xff0c;形成了…

Spring文件上傳

2019獨角獸企業重金招聘Python工程師標準>>> Spring文件上傳 1、所需依賴包&#xff1a;commons-fileupload-1.3.1.jar2、Maven配置文件pom.xml文件中加入依賴Jar包<dependency><groupId>commons-fileupload</groupId><artifactId>commons-…

中英離線翻譯mac_Instant Translate for Mac-即時翻譯Mac版下載 V1.3.0-PC6蘋果網

即時翻譯(Instant Translate)Mac版是一款Mac平臺的翻譯及辭典軟件&#xff0c;Instant Translate支持90的語言互翻譯&#xff0c;通過ControlS切換語言&#xff0c;并且支持發音功能&#xff0c;并且支持自動檢測語言并進行翻譯。軟件特色Instant Translate的主要特點&#xff…

基于Zookeeper使用ZkClient實現分布式鎖

有段時間沒寫博客了&#xff0c;在整理之前寫過的一套自定義框架&#xff0c;并且整理好上傳值github上了&#xff0c;也有一些新功能還在開發&#xff0c;歡迎大家使用&#xff1a;一個好用的Http接口請求工具組件 可能今天這篇文章跟之前的比有些跳躍性&#xff0c;一下子就…

算法題學到的一些小語言細節

1.要學會用i&#xff1b;可以簡化很多代碼&#xff1a;i&#xff1b;copyFromMe(i)&#xff1b;可以寫成&#xff1a;copyFromeMe(i) 2.StringBuffer也跟列表一樣有append函數&#xff1b; 3.if語句是分支不能進行循環&#xff0c;要寫成while才能替代循環里面的判斷 4. 這里的…

android 按鈕帶圖標 陰影_android中帶圖標的按鈕(ImageButton)怎么用

展開全部除了Android系統自帶的Button按鈕以外&#xff0c;還提供了帶圖標的按鈕ImageButton要制作帶圖標的按鈕&#xff0c;首先要在布局62616964757a686964616fe58685e5aeb931333337613163文件中定義ImageButton&#xff0c;然后通過setImageDrawable方法來設置要顯示的圖標。…

Zookeeper基礎常用操作以及ACL權限

這次將Zookeeper的一些基礎用法以及權限這塊的都補充一下在這篇博客中。 上篇博客介紹了基于ZooKeeper實現的分布式鎖&#xff0c;也介紹了一些ZooKeeper的節點類型以及監聽機制&#xff0c;今天這里就不作過多的介紹了&#xff0c;大家也可以自行的去官方文檔上看看更具體的介…

[中醫經絡學習一]足陽明胃經

人體有六臟&#xff08;心、肝、脾、肺、腎五臟&#xff0c;再加心包&#xff09;六腑&#xff08;胃、小腸、大腸、膀胱、膽、三焦&#xff09;&#xff0c;每個臟腑都聯接著一條經絡&#xff0c;一共12條經絡&#xff0c;稱“十二正經”&#xff0c;經絡的走向在四肢兩側基本…

ThreadLocal原理解析以及是否需要調用remove方法

平常的開發過程中&#xff0c;如果有個類不是線程安全的&#xff0c;比如SimpleDateFormat&#xff0c;要使這個類在并發的過程中是線程安全的&#xff0c;那么可以將變量設置位局部變量&#xff0c;不過存在的問題就是頻繁的創建對象&#xff0c;對性能和資源會有一定降低和消…

Maven基礎及概念

前言 今天就來聊聊Maven的基礎和一些比較概念性的東西&#xff0c;還有一些常用的Maven命令啥的&#xff0c;主要是某人腦子記不住&#xff0c;記在博客中讓她自己看吧&#xff0c;省的費心給她找。 后續的文章會聊到Maven的一些比較高級用法&#xff0c;像自定義插件&#x…

織夢縮略圖自動補齊絕對路徑_織夢生成文章內容縮略圖時自動加上域名絕對路徑...

今天又接了個織夢CMS的有償服務,客戶想要后臺添加文章內容的時候,縮略圖自動變成帶上絕對路徑的格式.比如我們默認的縮略圖是這樣的 /uploads/allimg/150814/123P2NB-0-lp.png 他想要的效果是這樣的 http://www.youwujun.com.cn/uploads/allimg/150814/123P2NB-0-lp.png大家懂我…

BUAA 436 孟竹的復習計劃(二維樹狀數組)

題目鏈接&#xff1a;http://acm.buaa.edu.cn/problem/436/ 題意&#xff1a;一個數列兩種操作&#xff1a;&#xff08;1&#xff09;將某個位置的數字改成另一個數字&#xff1b;&#xff08;2&#xff09;交換兩個位置的數字。每次操作之后輸出逆序數的個數。 思路&#xff…