评论

收藏

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

编程语言 编程语言 发布于:2021-10-07 16:37 | 阅读数:551 | 评论:0

目前在系统架构设计中使用Redis实现缓存,这篇文章主要介绍了使用Spring Data Redis实现数据缓存的方法,具有一定的参考价值,需要的朋友可以参考下
引言
目前很多系统为了解决数据读写的性能瓶颈,在系统架构设计中使用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三者之间的关系图如下所示。
DSC0000.png

5.spring cache
从spring3.1开始,spring框架提供了对cache的支持,提供了一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的作用。提供的主要注解有@cacheable、@cacheput、@cacheevict和@caching,具体见表1。
DSC0001.jpg

@cacheable的常用属性及说明如表2所示。
DSC0002.jpg

DSC0003.jpg

@cacheevict的常用属性见表4。@cacheput的常用属性同@cacheable。
DSC0004.jpg

当需要在类上或方法上同时使用多个注解时,可以使用@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
----------------------------------
从结果可以看到,使用缓存后,第二次查询没有执行查询方法体,直接返回了缓存中的数据;清除缓存后,再次查询就执行了查询方法体;修改数据后,相应的缓存数据也被修改了;不符合缓存条件的数据没有被缓存。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家
原文链接:https://www.jianshu.com/p/0dbe0a616898

关注下面的标签,发现更多相似文章