網站首頁 編程語言 正文
前言
今天在開發時發現一個奇怪的問題,我手動改完數據庫竟然不生效,反復確認環境無誤后猜測是緩存的問題,因為是新接手的項目,代碼還不熟悉,仔細一看,是開啟了二級緩存,并且存入Redis。
那今天就聊聊怎么優雅的用Redis作為Mybatis的二級緩存。
要優雅就選擇Mybatis-Plus
關于Mybatis-Plus的基礎設置就不多做介紹了,只說和二級緩存有關的。
首先在配置文件開啟二級緩存。
mybatis-plus: configuration: ? log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ? cache-enabled: true ? # 開啟二級緩存 mapper-locations: classpath:*/mapper/*.xml
Redis配置
這部分就是Redis的基本用法:
redis: ? host: 101.411.160.111 ? database: 0 ? port: 6311 ? password: 1111111
配置RedisTemplate
@Configuration public class RedisConfig { ? ?/** ? ? * 設置系列化方式、事務等配置 ? ? */ ? ?@Bean ? ?public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) ? { ? ? ? ?RedisTemplate<String,Serializable> redisTemplate = new RedisTemplate<>(); ? ? ? ? ?redisTemplate.setConnectionFactory(lettuceConnectionFactory); ? ? ? ?//設置key序列化方式string ? ? ? ?redisTemplate.setKeySerializer(new StringRedisSerializer()); ? ? ? ?//設置value的序列化方式json ? ? ? ?redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); ? ? ? ? ?redisTemplate.setHashKeySerializer(new StringRedisSerializer()); ? ? ? ?redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); ? ? ? ? ?redisTemplate.afterPropertiesSet(); ? ? ? ? ?return redisTemplate; ? } }
自定義Mybatis緩存
我們只需要實現Cache
這個接口。
@Slf4j public class MybatisRedisCache implements Cache { ? ?private static final String COMMON_CACHE_KEY = "mybatis"; ? ?// 讀寫鎖 ? ?private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true) ? ?private final RedisTemplate<String, Object> redisTemplate; ? ?private final String nameSpace; ? ? ?public MybatisRedisCache(String nameSpace) { ? ? ? ?if (nameSpace == null) { ? ? ? ? ? ?throw new IllegalArgumentException("Cache instances require an ID"); ? ? ? } ? ? ? ?redisTemplate = SpringUtil.getBean("redisTemplate"); ? ? ? ?this.nameSpace = nameSpace; ? } ? ?@Override ? ?public String getId() { ? ? ? ?return this.nameSpace; ? } ? ? ?private String getKeys() { ? ? ? ? ?return COMMON_CACHE_KEY + "::" + nameSpace + "::*"; ? } ? ? ?private String getKey(Object key) { ? ? ? ?return COMMON_CACHE_KEY + "::" + nameSpace + "::" + DigestUtils.md5Hex(String.valueOf(key)); ? } ? ?@Override ? ?public void putObject(Object key, Object value) { ? ? ? ?redisTemplate.opsForValue().set(getKey(key), value, 10, TimeUnit.MINUTES); ? } ? ?@Override ? ?public Object getObject(Object key) { ? ? ? ?try { ? ? ? ? ? ?return redisTemplate.opsForValue().get(getKey(key)); ? ? ? } catch (Exception e) { ? ? ? ? ? ?e.printStackTrace(); ? ? ? ? ? ?log.error("緩存出錯 "); ? ? ? } ? ? ? ?return null; ? } ? ? ?@Override ? ?public Object removeObject(Object o) { ? ? ? ?Object n = redisTemplate.opsForValue().get(getKey(o)); ? ? ? ?redisTemplate.delete(getKey(o)); ? ? ? ?return n; ? } ? ? ?@Override ? ?public void clear() { ? ? ? ?Set<String> keys = redisTemplate.keys(getKeys()); ? ? ? ?if (CollectionUtil.isNotEmpty(keys)) { ? ? ? ? ? ?assert keys != null; ? ? ? ? ? ?redisTemplate.delete(keys); ? ? ? } ? } ? ?@Override ? ?public int getSize() { ? ? ? ?Set<String> keys = redisTemplate.keys(getKeys()); ? ? ? ?if (CollectionUtil.isNotEmpty(keys)) { ? ? ? ? ? ?assert keys != null; ? ? ? ? ? ?return keys.size(); ? ? ? } ? ? ? ?return 0; ? } ? ?@Override ? ?public ReadWriteLock getReadWriteLock() { ? ? ? ?return this.readWriteLock; ? } }
測試
1.第一次查詢,走數據庫,并寫入緩存。
看看Redis的記錄:
2.第二次查詢,直接走緩存
3.重啟項目,依然可以直接查緩存
緩存命中率(Cache Hit Ratio)
不知道有沒有細心的同學注意到這樣一行日志:
Cache Hit Ratio [com.yitiao.mapper.ArticleMapper]: 0.5
最后這個0.5就是緩存命中率,代表一共查詢兩次,命中一次緩存一次。
一級緩存和二級緩存
一級緩存
一級緩存 Mybatis 的一級緩存是指 SQLSession,一級緩存的作用域是 SQlSession , Mabits 默認開啟一級緩存。 在同一個SqlSession中,執行相同的SQL查詢時;第一次會去查詢數據庫,并寫在緩存中,第二次會直接從緩存中取。 當執行SQL時候兩次查詢中間發生了增刪改的操作,則SQLSession的緩存會被清空。
每次查詢會先去緩存中找,如果找不到,再去數據庫查詢,然后把結果寫到緩存中。 Mybatis的內部緩存使用一個HashMap,key為hashcode+statementId+sql語句。Value為查詢出來的結果集映射成的java對象。 SqlSession執行insert、update、delete等操作commit后會清空該SQLSession緩存。
二級緩存
二級緩存 二級緩存是 mapper 級別的,Mybatis默認是沒有開啟二級緩存的。 第一次調用mapper下的SQL去查詢用戶的信息,查詢到的信息會存放到該 mapper 對應的二級緩存區域。 第二次調用 namespace 下的 mapper 映射文件中,相同的sql去查詢用戶信息,會去對應的二級緩存內取結果。
什么時候該開啟二級緩存
說實話,我遇到開啟二級緩存的時候并不多,因為緩存有利也有弊。
我的建議是如果發現接口耗時嚴重,可以在線上開啟二級緩存,開發環境關掉,為什么呢?
就拿今天我遇到的事來說,開發直接改庫不能立即生效,就很煩。
原文鏈接:https://juejin.cn/post/7130142146610331661
相關推薦
- 2022-05-13 Django-Cookies && Session
- 2023-01-18 Android事件與手勢操作詳解_Android
- 2022-05-01 Entity?Framework系統架構與原理介紹_基礎應用
- 2023-02-09 C++存儲持續性生命周期原理解析_C 語言
- 2024-03-05 git創建分支
- 2022-01-29 composer 安裝包提示內存不足的解決辦法
- 2022-03-15 ...has been blocked by CORS policy: Response to pr
- 2022-07-06 安裝pytorch報錯torch.cuda.is_available()=false問題的解決過程_
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支