MyBatis(十三)快取機制
阿新 • • 發佈:2021-08-17
13、快取
13.1 簡介
1、什麼是快取 [ Cache ]?
- 存在記憶體中的臨時資料。
- 將使用者經常查詢的資料放在快取(記憶體)中,使用者去查詢資料就不用從磁碟上(關係型資料庫資料檔案)查詢,從快取中查詢,從而提高查詢效率,解決了高併發系統的效能問題。
2、為什麼使用快取?
- 減少和資料庫的互動次數,減少系統開銷,提高系統效率。
3、什麼樣的資料能使用快取?
- 經常查詢並且不經常改變的資料。【可以使用快取】
13.2 Mybatis快取
- MyBatis包含一個非常強大的查詢快取特性,它可以非常方便地定製和配置快取。快取可以極大的提升查詢效率。
- MyBatis系統中預設定義了兩級快取:一級快取
-
- 預設情況下,只有一級快取開啟。(SqlSession級別的快取,也稱為本地快取)
- 二級快取需要手動開啟和配置,他是基於namespace級別的快取。
- 為了提高擴充套件性,MyBatis定義了快取介面Cache。我們可以通過實現Cache介面來自定義二級快取
13.3 一級快取
一級快取也叫本地快取:
- 與資料庫同一次會話期間查詢到的資料會放在本地快取中。
- 以後如果需要獲取相同的資料,直接從快取中拿,沒必須再去查詢資料庫;
測試
配置日誌,方便測試結果
//根據id查詢使用者
User queryUserById(@Param("id") int id);
<select id="queryUserById" resultType="user"> select * from user where id = #{id} </select>
@Test public void testQueryUserById(){ SqlSession session = MybatisUtils.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); User user2 = mapper.queryUserById(1); System.out.println(user2); System.out.println(user==user2); session.close(); }
測試結果
對比關閉快取結果
一級快取失效的四種情況
- 查詢不同的東西
- 增刪改操作,可能會改變原來的資料,所以必須會重新整理快取
- 查詢不同的Mapper.xml
- 手動清理快取
一級快取是SqlSession級別的快取,是一直開啟的,我們關閉不了它;
一級快取失效情況:沒有使用到當前的一級快取,效果就是,還需要再向資料庫中發起一次查詢請求
每個sqlSession中的快取相互獨立
小結:一級快取預設是開啟的,只在一次SqlSession中有效,也就是拿到連線到關閉連線的這個區間段!
一級快取相當於一個map
13.4 二級快取
- 二級快取也叫全域性快取,一級快取作用域太低了,所以誕生了二級快取
- 基於namespace級別的快取,一個名稱空間,對應一個二級快取;
- 工作機制
-
- 一個會話查詢一條資料,這個資料就會被放在當前會話的一級快取中;
- 如果當前會話關閉了,這個會話對應的一級快取就沒了;但是我們想要的是,會話關閉了,一級快取中的資料被儲存到二級快取中;
- 新的會話查詢資訊,就可以從二級快取中獲取內容;
- 不同的mapper查出的資料會放在自己對應的快取(map)中;
mybatis-config.xml 中開啟全域性快取
<setting name="cacheEnabled" value="true"/>
mapper.xml中設定使用二級快取
- 所有的實體類先實現序列化介面【Serializable】,否則就會報錯
- 測試程式碼
@Test
public void testQueryUserById(){
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
session.close();
User user2 = mapper2.queryUserById(1);
System.out.println(user2);
System.out.println(user==user2);
session2.close();
}
結論
- 只要開啟了二級快取,我們在同一個Mapper中的查詢,可以在二級快取中拿到資料
- 查出的資料都會被預設先放在一級快取中
- 只有會話提交或者關閉以後,一級快取中的資料才會轉到二級快取中
13.5 快取原理
13.6 EhCache自定義快取
第三方快取實現–EhCache: 檢視百度百科
Ehcache是一種廣泛使用的java分散式快取,用於通用快取;
要在應用程式中使用Ehcache,需要引入依賴的jar包
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
在mapper.xml中使用對應的快取即可
<mapper namespace = “org.acme.FooMapper” >
<cache type = “org.mybatis.caches.ehcache.EhcacheCache” />
</mapper>
編寫ehcache.xml檔案,如果在載入時未找到/ehcache.xml資源或出現問題,則將使用預設配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--
diskStore:為快取路徑,ehcache分為記憶體和磁碟兩級,此屬性定義磁碟的快取位置。引數解釋如下:
user.home – 使用者主目錄
user.dir – 使用者當前工作目錄
java.io.tmpdir – 預設臨時檔案路徑
-->
<diskStore path="./tmpdir/Tmp_EhCache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
<!--
defaultCache:預設快取策略,當ehcache找不到定義的快取時,則使用這個快取策略。只能定義一個。
-->
<!--
name:快取名稱。
maxElementsInMemory:快取最大數目
maxElementsOnDisk:硬碟最大快取個數。
eternal:物件是否永久有效,一但設定了,timeout將不起作用。
overflowToDisk:是否儲存到磁碟,當系統當機時
timeToIdleSeconds:設定物件在失效前的允許閒置時間(單位:秒)。僅當eternal=false物件不是永久有效時使用,可選屬性,預設值是0,也就是可閒置時間無窮大。
timeToLiveSeconds:設定物件在失效前允許存活時間(單位:秒)。最大時間介於建立時間和失效時間之間。僅當eternal=false物件不是永久有效時使用,預設是0.,也就是物件存活時間無窮大。
diskPersistent:是否快取虛擬機器重啟期資料 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:這個引數設定DiskStore(磁碟快取)的快取區大小。預設是30MB。每個Cache都應該有自己的一個緩衝區。
diskExpiryThreadIntervalSeconds:磁碟失效執行緒執行時間間隔,預設是120秒。
memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體。預設策略是LRU(最近最少使用)。你可以設定為FIFO(先進先出)或是LFU(較少使用)。
clearOnFlush:記憶體數量最大時是否清除。
memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,預設策略)、FIFO(先進先出)、LFU(最少訪問次數)。
FIFO,first in first out,這個是大家最熟的,先進先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的。如上面所講,快取的元素有一個hit屬性,hit值最小的將會被清出快取。
LRU,Least Recently Used,最近最少使用的,快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那麼現有快取元素中時間戳離當前時間最遠的元素將被清出快取。
-->
</ehcache>
Redis資料庫做快取
合理的使用快取,可以讓我們程式的效能大大提升