redis实现二级缓存

缓存的作用就是降低数据库的使用率,来减轻数据库的负担。我们平常的操作一般都是查>改,所以数据库的有些查操作是重复的,如果一直使用数据库就会有负担。Mybatis也会做缓存,也会有一级缓存和二级缓存:

  • 一级缓存:是SqlSession级别的缓存,使用HashMap数据结构来用于存储缓存数据的
  • 二级缓存:是mapper级别的缓存,其作用域是mapper的同一个namespace,不同的SqlSession执行两次相同namespace下的sql语句,并且传递的参数相同,返回的结果也相同时,第一次执行sql语句是会将数据从数据库中取出并存入缓存中,第二次查询时便会从缓存中直接获取数据
    二级缓存的实现大大的降低了数据库的负担,这里就来实现以下使用redis实现Mybatis的二级缓存。

我这里使用springboot快速搭建的项目>>>直通<<<,基本的环境如下:
jdk 1.7+
springboot maven mybatis项目
redis
mysql

二级缓存的实现

概述

redis二级缓存的实现,主要是重写了Cache.java的方法,自定义缓存,先来看看Cache的方法有哪些:

1

2

3

4

5

6

7
String getId();

void putObject(Object var1, Object var2);

Object getObject(Object var1);

Object removeObject(Object var1);

void clear();

int getSize();

ReadWriteLock getReadWriteLock();

这里有put、get、clear等方法,将在我们自己的缓存方法中重写这些方法

自定义缓存方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83
public class  implements Cache {

private static final Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);

private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

private RedisTemplate redisTemplate;

private String id;

private static final long EXPIRE_TIME_IN_MINUTES = 30;

public (String id){

if (id==null){

throw new IllegalArgumentException("Cache instances require an ID");

}

logger.info("=====================================Redis cache id = "+id);

this.id = id;

}

public String getId() {

return id;

}

public void putObject(Object key, Object value) {

logger.debug("==============================redis put= "+key);

RedisTemplate redisTemplate = getRedisTemplate();

ValueOperations opsForValue = redisTemplate.opsForValue();

opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);

}

public Object getObject(Object key) {

logger.debug("================================redis get================================");

RedisTemplate redisTemplate = getRedisTemplate();

ValueOperations opsForValue = redisTemplate.opsForValue();

return opsForValue.get(key);

}

public Object removeObject(Object key) {

logger.debug("==========================================redis remove==========================");

RedisTemplate redisTemplate = getRedisTemplate();

redisTemplate.delete(key);

return null;

}

public void clear() {

logger.debug("=====================================clear redis================================");

RedisTemplate redisTemplate = getRedisTemplate();

redisTemplate.execute(new RedisCallback() {

@Override

public Object doInRedis(RedisConnection connection) throws DataAccessException {

 大专栏  redis实现二级缓存
                connection.flushDb();

return "OK";

}

});

}

@Override

public int getSize() {

return 0;

}

@Override

public ReadWriteLock getReadWriteLock() {

return readWriteLock;

}

public RedisTemplate getRedisTemplate() {

if (redisTemplate == null) {

redisTemplate = ApplicationContextHolder.getBean("redisTemplate");

}

return redisTemplate;

}

public void setRedisTemplate(RedisTemplate redisTemplate) {

this.redisTemplate = redisTemplate;

}

}

这里需要用到redisTemplate,一开始我们初始化的是空的redisTemplate,这样的话redisTemplate.opsForValue()就是一个空指针异常,所以我们这里要getBean来获取,所以这里有一个ApplicationContextHolder工具类。

ApplicationContextHolder.java:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41
@Component

public class ApplicationContextHolder implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext ctx) throws BeansException {

applicationContext = ctx;

}

/**

* Get application context from everywhere

*

* @return

*/

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

/**

* Get bean by class

*

* @param clazz

* @param <T>

* @return

*/

public static <T> T getBean(Class<T> clazz) {

return applicationContext.getBean(clazz);

}

/**

* Get bean by class name

*

* @param name

* @param <T>

* @return

*/

@SuppressWarnings("unchecked")

public static <T> T getBean(String name) {

return (T) applicationContext.getBean(name);

}

}

二级缓存的使用

在mapper中添加自定义cache:

1
<cache type="com.yif.utils.MybatisRedisCache" eviction="LRU"/>

其中的eviction有4个不同的参数:

LRU :最近最少使用的:移除最长时间不被使用的对象
FIFO:先进先出:按进入缓存的顺序来移除他们
SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK:弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象

测试

测试前先在数据库中插入几条数据,用户测试二级缓存,其实二级缓存就是在原先完整的数据库操作程序中添加了一个自定义cache并在数据库mapper中引入使用。
1.启动redis,查看redis中的keys,可以看到现在是空的

2.启动程序,首先会运行MybatisRedisCache中的构造函数,在日志中看到id=com.yif.redis.model.User,即你的实例

3.运行查询步骤,MybatisRedisCache的运行顺序是:
第一次查询:
getObject()–>putObject()–>数据库查询

再看看redis中的keys,可以看出已经将存入了一个新的key

第二次相同的查询:
getObject()

这样就可以看出第一次查询是从数据库中查出然后将结果存入缓存中,第二次相同的查询是从缓存中就查出了,不再通过数据库查询。

注意:

在mapper文件中,主要两个参数:flushCache和useCache:

在select中,flushCache默认是false,不会清除本地缓存和二级缓存;useCache默认为true,表示进行二级缓存
在update、insert和delete中,flushCache默认为true,会清空本地缓存和二级缓存;而useCache在此是不存在的

所以在update语句中加上flushCache后更新数据库会清除redis的二级缓存,这样在进行下一次查询时,从redis中获取的便是自动更新后的数据(会将数据库的数据put到redis中),这里还有一个情况,也是自己遇到的。网上有很多资料写着MybatisRedisCache中的clear()方法是无用的,所以很多都没有写,这里我也没写,不过这样的话更新后就不会自动更新,所以自己又写了clear()方法,在数据库更新之后便会执行这个clear()方法。

原文地址:https://www.cnblogs.com/lijianming180/p/12284441.html

时间: 2024-10-08 17:16:12

redis实现二级缓存的相关文章

SpringMVC + MyBatis + Mysql + Redis(作为二级缓存) 配置

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 整体思路 pomxml中加入Maven依赖 引入applicationContextxml中引入redis配置 创建缓存实现类RedisCache 创建中间类RedisCacheTransfer完成RedisCachejedisConnectionFactory的静态注入 配置文件redisproperties mapper中加入MyBatis二级缓存 Mybatis全局配置 打印Sql日志方便测试 测试代码 项目环境: 在

SpringMVC +Spring + MyBatis + Mysql + Redis(作为二级缓存) 配置

转载:http://blog.csdn.net/xiadi934/article/details/50786293 项目环境: 在SpringMVC +Spring + MyBatis + MySQL.Redis部署在Linux虚拟机. 1.整体思路 参考Ehcache实现MyBatis二级缓存代码(Maven引用对应jar查阅) 使用Spring管理Redis连接池 模仿EhcacheCache,实现RedisCache 2.pom.xml中加入Maven依赖 1 <!-- spring-re

MySQL与Redis实现二级缓存

redis简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库 Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用 Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储 Redis支持数据的备份,即master-slave模式的数据备份 优势 性能极高 - Redis能读的速度是110

mybatis整合Redis实现二级缓存

Mybatis整合ehcache实现二级缓存 导入相关依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!--mybatis与ehcache整合--

mybatis结合redis实战二级缓存(六)

之前的文章中我们意见分析了一级缓存.二级缓存的相关源码和基本原理,今天我们来分享下了mybatis二级缓存和redis的结合,当然mybatis二级缓存也可以和ehcache.memcache.OSCache.Hazelcast结合使用.二级缓存相关的源码分享请参考<Mybatis源码分析之Cache二级缓存原理>.我们通过两种方式来实战,一种是自己编写缓存.另外一种是官方给出的demo地址:http://www.mybatis.org/redis-cache/ 一:自定义mybatis缓存

mybatis+redis实现二级缓存

在网上看了很多资料,发现例子都是千篇一律的相互复制.而且,使用的都是jedis的客户端..我这里使用的是redistemplate类实现. 缓存的原理..实现cache类接口,当哪个类需要缓存的时候,就直接将cache标签引入,并且制定我们的缓存类就可以了. 上代码: 1.引入spring-data-redis 1 <!-- redis服务 start--> 2 <dependency> 3 <groupId>org.springframework.data</g

Mybatis 使用redis 作为二级缓存时,无法通过cacheEnabled=false 将其关闭

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- 是

SpringBoot+Mybatis+redis实现二级缓存

对于查询比较多的项目可以考虑配置二级缓存,mybatis本身的二级缓存是缓存到本地,但是对于多个节点的项目来说,可能会出现数据不一致的问题,所以采用redis缓存,这样二级缓存的数据就可以缓存到内存,可实现多个节点项目的数据同步. 1.配置redis的连接 #redis gmall.redis.host=172.16.1.250 gmall.redis.port=6379 gmall.redis.pass=Gworld2017 gmall.redis.photo.database=6 #最大分配

mybatis-redis二级缓存

在mybatis一级缓存二级缓存中已经介绍过了二级缓存的大致原理.下面我们用redis来实现一下二级缓存.环境是springmvc+mybatis+redis 步骤一.引入redis相关的maven依赖 <!-- spring-redis实现 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifact