日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

jedis使用_Mybatis的二级缓存、使用Redis做二级缓存

發布時間:2024/9/3 数据库 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jedis使用_Mybatis的二级缓存、使用Redis做二级缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是二級緩存?

二級緩存和一級緩存的原理是一樣的,第一次查詢,會將數據放入緩存中,然后第二次查詢則會直接去緩存中取。但是一級緩存是基于的sqlSession,而二級緩存是基于mapper文件的namespace的,也就是說多個sqlSession可以共享一個mapper中的二級緩存區域,并且如何兩個mapper的namespace相同,即使兩個mapper,那這兩個mapper中執行sql查詢到的數據也將存在相同的二級緩存區域中

  • 如上圖sqlSession1在查詢時會從UserMapper的二級緩存中取,如果沒有則執行數據庫查詢操作。
  • 然后寫入到二級緩存中
  • sqlSession2則執行同樣的UserMapper查詢時,會從UserMapper的二級緩存中取,此時的二級緩存中已經有內容了,所以就可以直接取到,不再與數據庫交互。
  • sqlSession3在執行事務操作(插入、更新、刪除)時,會清空UserMapper的二級緩存

1. 開啟二級緩存

如何使用二級緩存:

mybatis中,一級緩存是默認開啟的,但是二級緩存需要配置才可以使用

  • 在全局配置文件sqlMapConfig.xml中加入如下代碼:
    <!--開啟二級緩存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
  • 其次在哪個namespace中開啟二級就在哪里配置,因為mybatis有注解和xml兩種方式所以:
    • 注解


    注解擴展:
    //我們默認使用的是mybatis自帶的二級緩存,它的實現在PerpetualCache類中,所以可以寫成 @CacheNamespace(implementation = PerpetualCache.class) //如果是使用redis作為二級緩存的話,下面第二部分會講到

    • xml


    這樣就開啟了UserMapper的二級緩存

  • 測試一:
    我們要根據用戶id查詢用戶信息:
  • 注意:將緩存的pojo實現Serializable接口,為了將緩存數據取出執行反序列化操作,因為二級緩存的存儲介質多種多樣,不一定只在內存中,也可能在硬盤中,如果我們要再取出這個緩存的話,就需要反序列化了。所以mybatis的pojo都去實現Serializable接口


    最后執行看到打印日志:

    為什么System.out.println(user1==user2)為false ?二級緩存和一級緩存不同,二級緩存緩存的不是對象,而是數據,在第二次查詢時底層重新創建了一個User對象,并且把二級緩存中的數據重新封裝成了對象并返回。所以user1和user2不是一個對象。

  • 測試二:
    我們在測試二中進行一下事務操作,看看是否能清空二級緩存:
  • ? 增加了一個修改操作,發現執行了兩個select,說明提交事務會刷新二級緩存

    userCache和flushCache

    還可以配置userCache和flushCache

    • userCache : 是用來設置是否禁用二級緩存的,在statement中設置可以禁用當前select語句的二級緩存,即每次查詢都會發出sql。默認情況為true.

    • flushCache : 在mapper的同一個namespace中,如果有其它的增刪改操作后需要刷新緩存,如果部執行刷新緩存會出現臟讀。
      設置statement配置中的flushCache="true",即刷新緩存,如果改成false則不會刷新,有可能出現臟讀。所以一般情況下沒必要改

    Mybatis二級緩存和一級緩存一樣也是使用到了org.apache.ibatis.cache.impl.PerpetualCache
    這個類是mybatis的默認緩存類,同時,想要自定義緩存必須實現cache接口

    2. 使用Redis實現二級緩存

    Mybatis自帶的二級緩存是有缺點的,就是這個緩存是單服務器進行工作的,無法實現分布式緩存。

    所以為了解決這個問題,必須找一個分布式緩存專門存放緩存數據。

    如何使用

    mybatis提供了一個針對cache接口的redis實現類,在mybatis-redis包中

  • 首先我們引入jar包
    <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>1.0.0-beta2</version> </dependency>
  • 修改Mapper.xml文件
    //**********XML方式***********: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lagou.mapper.IUserMapper"> //表示針對于當前的namespace開啟二級緩存 <cache type="org.mybatis.caches.redis.RedisCache" /> <select id="findAll" resultType="com.lagou.pojo.User" useCache="true"> select * from user </select>
    //*******注解方式********** @CacheNamespace(implementation = RedisCache .class) public interface UserMapper { //根據id查詢用戶 注解使用 @Select("select * from user where id=#{id}") public User findById(Integer id);
    這個類同樣實現了Cache接口
  • 配置redis的配置文件
    redis.host=localhost redis.port=6379 redis.connectionTimeout=5000 redis.password= redis.database=0
    測試方法同自帶的二級緩存一樣。
  • 3. Redis二級緩存源碼分析

    RedisCache和Mybatis二級緩存的方案都差不多,無非是實現Cache接口,并使用jedis操作緩存,不過在設計細節上有點區別。
    我們帶著問題分析源碼:

    • 在RedisCache類中如何向redis中進行緩存值的存取 ?
    • 使用了哪種數據結構 ?
    package org.mybatis.caches.redis; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;//首先其實現了Cache接口,被mybatis初始化的時候的CacheBuilder創建 //創建方式就是調用了下面的有參構造 public final class RedisCache implements Cache {private final ReadWriteLock readWriteLock = new DummyReadWriteLock();private String id;private static JedisPool pool;//有參構造 public RedisCache(final String id) {if (id == null) {throw new IllegalArgumentException("Cache instances require an ID");}this.id = id;//RedisConfigurationBuilder調用parseConfiguration()方法創建RedisConfig對象RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();//構建Jedis池pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(),redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(),redisConfig.getDatabase(), redisConfig.getClientName());}//模板方法,下面的putObject和getObject、removeObject都會用到這個方法private Object execute(RedisCallback callback) {Jedis jedis = pool.getResource();try {return callback.doWithRedis(jedis);} finally {jedis.close();}}//。。。。。。。。省略部分代碼 @Overridepublic void putObject(final Object key, final Object value) {execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));return null;}});}@Overridepublic Object getObject(final Object key) {return execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {return SerializeUtil.unserialize(jedis.hget(id.toString().getBytes(), key.toString().getBytes()));}});}@Overridepublic Object removeObject(final Object key) {return execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {return jedis.hdel(id.toString(), key.toString());}});}}
  • RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
  • RedisConfig中封裝了默認的Redis配置信息


    這個方法讀取了我們配置在/resource/redis.properties這個文件
    RedisConfig后構建了Jedis池

  • put方法
    private Object execute(RedisCallback callback) { Jedis jedis = pool.getResource(); try { return callback.doWithRedis(jedis); } finally { jedis.close(); } } public void putObject(final Object key, final Object value) { execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value)); return null; } }); }
    我們可以看到,put方法調用了模板方法得到 一個jedis鏈接,然后調用doWithRedis()方法
    jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));
    可以很清楚的看到,mybatis-redis在存儲數據的時候,是使用的hash結構,把cache的id作為這個hash的key (cache的id在mybatis中就是mapper的namespace);這個mapper中的查詢緩存數據作為 hash的field,需要緩存的內容直接使用SerializeUtil存儲,SerializeUtil和其他的序列化類差不多,負責對象的序列化和反序列化;
  • 轉載:https://www.cnblogs.com/isdxh/p/13963636.html

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的jedis使用_Mybatis的二级缓存、使用Redis做二级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。