Mybatis緩存

MyBatis提供查詢緩存,如果緩存中有數(shù)據(jù),則直接從緩存中獲取,沒有則從數(shù)據(jù)庫查詢,用以減輕數(shù)據(jù)壓力,提高系統(tǒng)性能。MyBatis的緩存分為一級緩存和二級緩存,默認(rèn)情況下一級緩存是開啟的,且是不能關(guān)閉的。一級緩存是SqlSession級別的,當(dāng)同一個 SqlSession中進(jìn)行相同的sql查詢時,第二次以后的查詢都是從一級緩存中獲取,一級緩存最多緩存1024條sql。二級緩存是Mapper級別的,可以跨SqlSession,不同SqlSession可共享。

MyBatis緩存機制

MyBatis緩存機制.png

MyBatis緩存實現(xiàn)原理

Executor接口.png

MyBatis認(rèn)為的完全相同的查詢,只要保證statementId,rowBounds,最后生成的SQL語句,以及這個SQL語句所需要的參數(shù)完全一致就可以了。

一級緩存

一級緩存是如何組織的?

一級緩存是SqlSession級別的緩存。在操作數(shù)據(jù)庫時需要構(gòu)造 sqlSession對象,并為SqlSession對象創(chuàng)建一個Executor執(zhí)行器,而緩存信息以HashMap的形式維護(hù)在這個Executor中,MyBatis將緩存和緩存操作封裝在Cache中。


SqlSession對象、Executor對象、Cache對象之間的關(guān)系.png

一級緩存原理

第一次發(fā)出一個查詢sql,sql查詢結(jié)果寫入SqlSession的一級緩存中,緩存使用的數(shù)據(jù)結(jié)構(gòu)為(HashMap)。
同一個SqlSession發(fā)出第二次查詢時,就從緩存中獲取。如果兩次中間出現(xiàn)commit操作(update/insert/delete),則本SqlSession的一級緩存全部清空(為了緩存中記錄最新的數(shù)據(jù),避免臟讀),從數(shù)據(jù)庫查詢。

  • key:mapperID+offset+limit+Sql+所有的入?yún)?/strong>
  • value:查詢結(jié)果

一級緩存的生命周期

  1. 開啟數(shù)據(jù)庫會話,創(chuàng)建新的SqlSession對象,SqlSession對象中會有一個Executor對象,Executor對象持有新的PerpetualCache對象;會話結(jié)束時,SqlSession對象以及Executor對象和PerpetualCache對象一并銷毀。
  2. SqlSession調(diào)用close()方法,會釋放掉一級緩存PerpetualCache對象,一級緩存不可用。
  3. 如果SqlSession調(diào)用clearCache()方法,會清空PerpetualCache對象,但對象仍可用。
  4. SqlSession執(zhí)行任何一個insert()、update()、delete()操作,會清空PerpetualCache對象,但對象仍可用。

一級緩存的工作流程

  1. 對于某個查詢,根據(jù)statementId、params、rowBounds來構(gòu)建key值,根據(jù)key值去緩存Cache中查找結(jié)果;
  2. 判斷從Cache中根據(jù)特定的key值取的數(shù)據(jù)數(shù)據(jù)是否為空,即是否命中;
  3. 如果命中,則直接返回查詢結(jié)果;
  4. 如果沒有命中:
  • 數(shù)據(jù)庫中查詢結(jié)果;
  • 將key和查詢結(jié)果分別作為key和value存入Cache緩存中;
  • 查詢結(jié)果返回。
  1. 結(jié)束。

一級緩存性能分析

  1. Session級別的一級緩存設(shè)計比較簡單,只使用了HashMap來維護(hù),并沒有對HashMap的容量和大小進(jìn)行限制。
  • SqlSession的生存時間很短。使用一個SqlSession對象執(zhí)行的操作不會太多,執(zhí)行完就會消亡;
  • 對于某一個SqlSession對象而言,只要執(zhí)行commit操作(update、insert、delete),都會將這個SqlSession對象中對應(yīng)的一級緩存清空掉,所以一般情況下不會出現(xiàn)緩存過大,影響JVM內(nèi)存空間的問題;
  • 可以手動地釋放掉SqlSession對象中的緩存。
  1. 一級緩存是粗粒度緩存,沒有更新緩存和緩存過期概念。
  • 對于數(shù)據(jù)變化頻率很大,并且需要高時效準(zhǔn)確性的數(shù)據(jù)要求,我們使用SqlSession查詢的時候,要控制好SqlSession的生存時間,SqlSession的生存時間越長,它其中緩存的數(shù)據(jù)有可能就越舊,從而造成和真實數(shù)據(jù)庫的誤差;同時對于這種情況,用戶也可以手動地適時清空SqlSession中的緩存;
  • 對于只執(zhí)行、并且頻繁執(zhí)行大范圍的select操作的SqlSession對象,SqlSession對象的生存時間不應(yīng)過長。

二級緩存

二級緩存是mapper級別的,mapper以命名空間為單位創(chuàng)建緩存數(shù)據(jù)結(jié)構(gòu)(HashMap),二級緩存通過CachingExecutor(Executor的代理對象)實現(xiàn)。

二級緩存原理

所有查詢操作,在CachingExecutor都會先匹配緩存中是否存在,否則查詢數(shù)據(jù)庫。

  • key:mapperID+offset+limit+Sql+所有的入?yún)?/strong>
  • value:查詢結(jié)果

二級緩存工作模式

二級緩存機制關(guān)鍵在于Executor對象。若配置【cacheEnable=true】,則為SqlSession創(chuàng)建Executor加上一個裝飾者(CachingExecutor)。這時由CachingExecutor對象來完成操作請求。
CachingExecutor對于查詢請求,先判斷在Application級別的二級緩存是否有結(jié)果,如果有直接返回結(jié)果。若沒有,再交給真正的Executor對象來完成查詢,之后CachingExecutor會將真正Executor返回的結(jié)果放置在緩存中,在返回給用戶。


使用二級緩存工作模式.png

二級緩存劃分

MyBatis并不簡單將Application就只有一個Cache緩存對象,它將緩存劃分的更新,即是mapper級別的(即每一個mapper一個緩存對象)。

1. 為每一個mapper分配一個緩存對象(對于每一個mapper.xml,在其中使用<cache> 節(jié)點)。

使用cache節(jié)點配置.png

2. 多個mapper共用一個緩存對象(使用<cache-ref namespace="">節(jié)點,來指定你的這個Mapper使用到了哪一個Mapper的Cache緩存)。

cache-ref共用緩存.png

二級緩存的開啟

MyBatis對二級緩存的支持粒度較細(xì),需要具體指定到某條查詢語句上。如果要開啟二級緩存,需做到如下三點:

  1. MyBatis支持二級緩存的總開關(guān):全局配置變量參數(shù)【cacheEnabled=true】。
  2. 該select語句所在的Mapper,配置了<cache> 或<cached-ref>節(jié)點,并且有效。
  3. 該select語句的參數(shù) useCache=true。

二級緩存的實現(xiàn)

MyBatis 對于二級緩存的實現(xiàn)非常靈活,自己內(nèi)部實現(xiàn)了Cache的一系列的實現(xiàn)類,并提供了各種緩存刷新策略LRU、FIFO等。同時它也允許自定義Cache接口實現(xiàn),需實現(xiàn)org.apache.ibatis.cache.Cache接口,然后將Cache的實現(xiàn)類配置在<cache type="">節(jié)點的type屬性上。此外,它也支持與第三方緩存庫如Memecached的集成。

二級緩存的實現(xiàn)有三種選擇:

  1. MyBatis自身提供的緩存實現(xiàn);

    • MyBatis定義了大量的Cache的裝飾器來增強Cache緩存的功能


      Cache裝飾器.png
    • 對于每個Cache而言,都有容量限制,MyBatis提供了各種策略來對Cache緩存的容量進(jìn)行控制,以及對于Cache中的數(shù)據(jù)進(jìn)行刷新和置換。主要有以下幾個刷新和置換策略:

      LRU:Least Recently Used,最近最少使用算法,即緩存中容量滿了,會將緩存最近最少使用的數(shù)據(jù)清楚,添加上新的記錄。

      FIFO:First In First Out,先進(jìn)先出算法,即緩存中容量滿了,會將最先進(jìn)來的數(shù)據(jù)清楚。

      Scheduled:指定時間間隔清空算法,該算法會以指定的某一個時間間隔將Cache緩存中的數(shù)據(jù)清空。

  2. 用戶自定義的Cache接口實現(xiàn);

  3. 跟第三方內(nèi)存緩存庫的集成;

二級緩存應(yīng)用場景

  • 使用場景
    對于訪問響應(yīng)速度要求高,但是實時性不高的查詢,可以采用二級緩存技術(shù)。
  • 注意事項
    在使用二級緩存的時候,要設(shè)置一下刷新間隔(cache標(biāo)簽中有一個flashInterval屬性)來定時刷新二級緩存,這個刷新間隔根據(jù)具體需求來設(shè)置,比如設(shè)置30分鐘、60分鐘等,單位為毫秒。

二級緩存局限性

Mybatis二級緩存對細(xì)粒度的數(shù)據(jù)級別的緩存實現(xiàn)不好。

  • 場景
    對商品信息進(jìn)行緩存,由于商品信息查詢訪問量大,但是要求用戶每次查詢都是最新的商品信息,此時如果使用二級緩存,就無法實現(xiàn)當(dāng)一個商品發(fā)生變化只刷新該商品的緩存信息而不刷新其他商品緩存信息,因為二級緩存是mapper級別的,當(dāng)一個商品的信息發(fā)送更新,所有的商品信息緩存數(shù)據(jù)都會清空。

  • 解決方法
    此類問題,需要在業(yè)務(wù)層根據(jù)需要對數(shù)據(jù)有針對性的緩存。
    比如可以對經(jīng)常變化的 數(shù)據(jù)操作單獨放到另一個namespace的mapper中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 緩存技術(shù)是一種“以空間換時間”的設(shè)計理念,是利用內(nèi)存空間資源來提高數(shù)據(jù)檢索速度的有效手段之一。Mybatis包含一...
    不知名的蛋撻閱讀 4,249評論 0 7
  • 一級緩存 MyBatis 包含了一個非常強大的查詢緩存特性,它可以非常方便地配置和定制。MyBatis 3 中的緩...
    SuBHFeng閱讀 349評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,896評論 28 54
  • 信任包括信任自己和信任他人 很多時候,很多事情,失敗、遺憾、錯過,源于不自信,不信任他人 覺得自己做不成,別人做不...
    吳氵晃閱讀 6,391評論 4 8
  • 步驟:發(fā)微博01-導(dǎo)航欄內(nèi)容 -> 發(fā)微博02-自定義TextView -> 發(fā)微博03-完善TextView和...
    dibadalu閱讀 3,429評論 1 3

友情鏈接更多精彩內(nèi)容