策略 | 一致性 | 维护成本 |
利用Redis的缓存淘汰策略被动更新 | 最差 | 最低 |
利用TTL被动更新 | 较差 | 较低 |
在更新数据库时主动更新 | 较强 | 最高 |
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-redisartifactId>
- dependency>
- #开发配置
- spring:
- #数据源配置
- datasource:
- url: jdbc:mysql://192.168.127.128:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
- username: root
- password: root
- driver-class-name: com.mysql.jdbc.Driver
- type: com.alibaba.druid.pool.DruidDataSource
-
- redis:
- host: 192.168.127.128
- port: 6379
- jedis:
- pool:
- min-idle: 0
- max-idle: 8
- max-active: 8
- max-wait: -1ms
-
- #公共配置与profiles选择无关
- mybatis:
- typeAliasesPackage: com.lagou.rcache.entity
- mapperLocations: classpath:mapper/*.xml
ApplicationContextHolder 用于注入RedisTemplate
- package com.lagou.rcache.utils;
-
- import org.springframework.beans.BeansException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import org.springframework.stereotype.Component;
-
- @Component
- public class ApplicationContextHolder implements ApplicationContextAware {
- private static ApplicationContext ctx;
-
- @Override
- //向工具类注入applicationContext
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- ctx = applicationContext; //ctx就是注入的applicationContext
- }
-
- //外部调用ctx
- public static ApplicationContext getCtx() {
- return ctx;
- }
-
- public static
T getBean(Class tClass) { - return ctx.getBean(tClass);
- }
-
- @SuppressWarnings("unchecked")
- public static
T getBean(String name) { - return (T) ctx.getBean(name);
- }
- }
RedisCache 使用redis实现mybatis二级缓存
- package com.lagou.rcache.utils;
-
- import org.apache.ibatis.cache.Cache;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.data.redis.core.RedisCallback;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.ValueOperations;
-
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
-
- /**
- * 使用redis实现mybatis二级缓存
- */
- public class RedisCache implements Cache {
- //缓存对象唯一标识
- private final String id; //orm的框架都是按对象的方式缓存,而每个对象都需要一个唯一标识.
- //用于事务性缓存操作的读写锁
- private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
- //处理事务性缓存中做的
- //操作数据缓存的--跟着线程走的
- private RedisTemplate redisTemplate; //Redis的模板负责将缓存对象写到redis服务器里面去
- //缓存对象的是失效时间,30分钟
- private static final long EXPRIRE_TIME_IN_MINUT = 30;
-
- //构造方法---把对象唯一标识传进来
- public RedisCache(String id) {
- if (id == null) {
- throw new IllegalArgumentException("缓存对象id是不能为空的");
- }
- this.id = id;
- }
-
- @Override
- public String getId() {
- return this.id;
- }
-
- //给模板对象RedisTemplate赋值,并传出去
- private RedisTemplate getRedisTemplate() {
- if (redisTemplate == null) { //每个连接池的连接都要获得RedisTemplate
- redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
- }
- return redisTemplate;
- }
-
- /*
- 保存缓存对象的方法
- */
- @Override
- public void putObject(Object key, Object value) {
- try {
- RedisTemplate redisTemplate = getRedisTemplate();
- //使用redisTemplate得到值操作对象
- ValueOperations operation = redisTemplate.opsForValue();
- //使用值操作对象operation设置缓存对象
- operation.set(key, value, EXPRIRE_TIME_IN_MINUT, TimeUnit.MINUTES);
- //TimeUnit.MINUTES系统当前时间的分钟数
- System.out.println("缓存对象保存成功");
- } catch (Throwable t) {
- System.out.println("缓存对象保存失败" + t);
- }
- }
-
- /*
- 获取缓存对象的方法
- */
- @Override
- public Object getObject(Object key) {
- try {
- RedisTemplate redisTemplate = getRedisTemplate();
- ValueOperations operations = redisTemplate.opsForValue();
- Object result = operations.get(key);
- System.out.println("获取缓存对象");
- return result;
- } catch (Throwable t) {
- System.out.println("缓存对象获取失败" + t);
- return null;
- }
- }
-
- /*
- 删除缓存对象
- */
- @Override
- public Object del(Object key) {
- try {
- RedisTemplate redisTemplate = getRedisTemplate();
- redisTemplate.delete(key);
- System.out.println("删除缓存对象成功!");
- } catch (Throwable t) {
- System.out.println("删除缓存对象失败!" + t);
- }
- return null;
- }
-
- /*
- 清空缓存对象
- 当缓存的对象更新了的化,就执行此方法
- */
- @Override
- public void clear() {
- RedisTemplate redisTemplate = getRedisTemplate();
- //回调函数
- redisTemplate.execute((RedisCallback) collection -> {
- collection.flushDb();
- return null;
- });
- System.out.println("清空缓存对象成功!");
- }
-
- //可选实现的方法
- @Override
- public int getSize() {
- return 0;
- }
-
- @Override
- public ReadWriteLock getReadWriteLock() {
- return readWriteLock;
- }
- }
- "1.0" encoding="UTF-8"?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
- <mapper namespace="com.lagou.rcache.dao.UserDao">
- <cache type="com.lagou.rcache.utils.RedisCache"/>
- <resultMap id="BaseResultMap" type="com.lagou.rcache.entity.TUser">
- <id column="id" property="id" jdbcType="INTEGER"/>
- <result column="name" property="name" jdbcType="VARCHAR"/>
- <result column="address" property="address" jdbcType="VARCHAR"/>
- resultMap>
- <sql id="Base_Column_List">
- id, name, address
- sql>
- <select id="selectUser" resultMap="BaseResultMap">
- select
- <include refid="Base_Column_List"/>
- from tuser
- select>
- mapper>
- package com.lagou.rcache;
-
- import org.mybatis.spring.annotation.MapperScan;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cache.annotation.EnableCaching;
-
- @SpringBootApplication
- @MapperScan("com.lagou.rcache.dao")
- @EnableCaching
- public class RcacheApplication {
- public static void main(String[] args) {
- SpringApplication.run(RcacheApplication.class, args);
- }
- }
注意:这里我只是介绍了其相关的核心代码,其他部分的代码进行了省略。例如:映射实体类、controller访问调用mybatis。这里只是简要的介绍,你还可以自己实现,最重要的是实现Mybatis的Catch接口。