使用Spring Data Redis实现数据缓存的方法

作者:JavaQ 时间:2021-08-02 10:19:25 

引言

目前很多系统为了解决数据读写的性能瓶颈,在系统架构设计中使用Redis实现缓存,Spring框架为了让开发人员更加方便快捷的使用Redis实现缓存,对Redis的操作进行了包装。

0.缓存

个人理解的缓存是指用于存储频繁使用的数据的空间,关注点是存储数据的空间和使用频繁的数据。缓存技术,简单的说就是先从缓存中查询数据是否存在,存在则直接返回,不存在再执行相应的操作获取数据,并将获取的数据存储到缓存中,它是一种提升系统性能的重要方法。

1.Redis

Redis是一个开源的、内存存储key-value类型的数据结构服务器,可用作数据库、高速缓存和消息队列代理。它支持的数据类型有字符串、哈希表、列表、集合、有序集合等,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供分区功能。

2.jedis

jedis是Redis的Java版客户端实现,也是官方推荐的Java版客户端。它封装了对Redis的各种操作,并且支持事务、管道及有jedis自身实现的分布式。

3.Spring Data Redis

Spring Data是Spring框架中的一个主要项目,目的是为了简化构建基于Spring框架应用的数据访问,包括非关系数据库、Map-Reduce框架、云数据服务等,另外也包含对关系数据库的访问支持。
Spring Data Redis是Spring Data项目中的一个主要模块,实现了对jedis客户端API的高度封装,使对Redis的操作更加便捷。

4.关系图

Redis、jedis、Spring Data Redis三者之间的关系图如下所示。

使用Spring Data Redis实现数据缓存的方法

5.Spring Cache

从Spring3.1开始,Spring框架提供了对Cache的支持,提供了一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的作用。提供的主要注解有@Cacheable、@CachePut、@CacheEvict和@Caching,具体见表1。

使用Spring Data Redis实现数据缓存的方法

@Cacheable的常用属性及说明如表2所示。

使用Spring Data Redis实现数据缓存的方法

使用Spring Data Redis实现数据缓存的方法

@CacheEvict的常用属性见表4。@CachePut的常用属性同@Cacheable。

使用Spring Data Redis实现数据缓存的方法

当需要在类上或方法上同时使用多个注解时,可以使用@Caching,如@Caching(cacheable = @Cacheable("User"), evict = {@CacheEvict("Member"), @CacheEvict(value = "Customer", allEntries = true)})

6.使用示例

下面使用Spring Data Reds、Redis和jedis实现一个简单的数据缓存。

1)依赖配置

示例使用了gradle,所以需要在build.gradle中加入如下依赖配置来管理所需要的jar。


compile "org.springframework.data:spring-data-redis:1.7.2.RELEASE"
compile "redis.clients:jedis:2.7.2"
testCompile "junit:junit:4.12"

2)Redis配置

示例连接的是本地的Redis,redis.properties配置如下。


# Redis settings
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.dbIndex=0
redis.expiration=3000
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true

3)Spring配置

Spring的配置文件如下。


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:cache="http://www.springframework.org/schema/cache"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
 <context:component-scan base-package="redis.cache"/>
 <context:annotation-config/>
 <cache:annotation-driven cache-manager="redisCacheManager"/>
 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="locations">
     <list>
       <value>classpath:redis.properties</value>
     </list>
   </property>
 </bean>
 <!-- 配置JedisPoolConfig实例 -->
 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
   <property name="maxIdle" value="${redis.maxIdle}"/>
   <property name="maxTotal" value="${redis.maxActive}"/>
   <property name="maxWaitMillis" value="${redis.maxWait}"/>
   <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
 </bean>
 <!-- 配置JedisConnectionFactory -->
 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
   <property name="hostName" value="${redis.host}"/>
   <property name="port" value="${redis.port}"/>
   <property name="password" value="${redis.pass}"/>
   <property name="database" value="${redis.dbIndex}"/>
   <property name="poolConfig" ref="poolConfig"/>
 </bean>
 <!-- 配置RedisTemplate -->
 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
   <property name="connectionFactory" ref="jedisConnectionFactory"/>
 </bean>
 <!-- 配置RedisCacheManager -->
 <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
   <constructor-arg name="redisOperations" ref="redisTemplate"/>
   <property name="defaultExpiration" value="${redis.expiration}"/>
 </bean>
</beans>

4)Service

示例代码的Servicer如下。


@Service("userService")
public class UserService {
 @Cacheable(value = "User", key = "'UserId_' + #id",condition = "#id<=110")
 public String queryFullNameById(long id) {
   System.out.println("execute queryFullNameById method");
   return "ZhangSanFeng";
 }

@CacheEvict(value = "User", key = "'UserId_' + #id")
 public void deleteById(long id) {
   System.out.println("execute deleteById method");
 }

@CachePut(value = "User", key = "'UserId_' + #id")
 public String modifyFullNameById(long id, String newName) {
   System.out.println("execute modifyFullNameById method");
   return newName;
 }
}

5)测试


 @Test
 public void test() {
   ApplicationContext context = new ClassPathXmlApplicationContext("redisCacheContext.xml");
   UserService userService = (UserService) context.getBean("userService");
   System.out.println("第一次执行查询:" + userService.queryFullNameById(110L));
   System.out.println("----------------------------------");

System.out.println("第二次执行查询:" + userService.queryFullNameById(110L));
   System.out.println("----------------------------------");

userService.deleteById(110L);
   System.out.println("----------------------------------");

System.out.println("清除缓存后查询:" + userService.queryFullNameById(110L));
   System.out.println("----------------------------------");

System.out.println(userService.modifyFullNameById(110L, "ZhangJunBao"));
   System.out.println("----------------------------------");

System.out.println("修改数据后查询:" + userService.queryFullNameById(110L));
   System.out.println("----------------------------------");

System.out.println("第一次执行查询:" + userService.queryFullNameById(112L));
   System.out.println("----------------------------------");

System.out.println("第二次执行查询:" + userService.queryFullNameById(112L));
   System.out.println("----------------------------------");
 }

6)测试结果

输出结果如下。

execute queryFullNameById method
第一次执行查询:ZhangSanFeng
----------------------------------
第二次执行查询:ZhangSanFeng
----------------------------------
execute deleteById method
----------------------------------
execute queryFullNameById method
清除缓存后查询:ZhangSanFeng
----------------------------------
execute modifyFullNameById method
ZhangJunBao
----------------------------------
修改数据后查询:ZhangJunBao
----------------------------------
execute queryFullNameById method
第一次执行查询:ZhangSanFeng
----------------------------------
execute queryFullNameById method
第二次执行查询:ZhangSanFeng
----------------------------------

从结果可以看到,使用缓存后,第二次查询没有执行查询方法体,直接返回了缓存中的数据;清除缓存后,再次查询就执行了查询方法体;修改数据后,相应的缓存数据也被修改了;不符合缓存条件的数据没有被缓存。

来源:https://www.jianshu.com/p/0dbe0a616898

标签:Spring,Data,Redis,缓存
0
投稿

猜你喜欢

  • Java转JSON串的几种方式

    2023-08-24 07:38:47
  • TransmittableThreadLocal解决线程间上下文传递烦恼

    2023-11-09 17:09:35
  • Java JDK动态代理实现原理实例解析

    2022-04-23 05:19:10
  • 25行Java代码将普通图片转换为字符画图片和文本的实现

    2023-11-24 02:04:26
  • java连接MySQl数据库实例代码

    2021-12-18 18:19:36
  • Spring Cloud Gateway网关XSS过滤方式

    2021-08-07 13:16:53
  • Java中关于二叉树层序遍历深入了解

    2023-07-26 07:06:09
  • Java中BigDecimal的加减乘除、比较大小与使用注意事项

    2022-02-17 21:24:09
  • 举例说明Java设计模式编程中ISP接口隔离原则的使用

    2023-11-20 11:07:40
  • idea全局搜索快捷键超详细总结(推荐!)

    2021-08-12 20:16:18
  • c语言动态数组示例

    2023-11-02 22:56:44
  • Java二分查找算法实例详解

    2022-07-09 14:33:55
  • Java异常的处理机制

    2023-12-03 15:33:19
  • Java File类提供的方法与操作

    2023-08-29 09:10:41
  • 详细了解JAVA NIO之Buffer(缓冲区)

    2022-08-18 00:59:28
  • postman测试传入List<String>参数方式

    2022-10-13 01:34:40
  • Java基于rest assured实现接口测试过程解析

    2022-07-25 09:30:25
  • Java ClassLoader虚拟类实现代码热替换的示例代码

    2022-06-25 03:08:52
  • Java基础之二叉搜索树的基本操作

    2023-07-08 10:07:07
  • Springboot jar主清单属性丢失解决方案

    2022-04-06 05:30:26
  • asp之家 软件编程 m.aspxhome.com