溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

發(fā)布時(shí)間:2020-08-23 10:44:21 來源:腳本之家 閱讀:157 作者:JavaQ 欄目:編程語言

引言

目前很多系統(tǒng)為了解決數(shù)據(jù)讀寫的性能瓶頸,在系統(tǒng)架構(gòu)設(shè)計(jì)中使用Redis實(shí)現(xiàn)緩存,Spring框架為了讓開發(fā)人員更加方便快捷的使用Redis實(shí)現(xiàn)緩存,對(duì)Redis的操作進(jìn)行了包裝。

0.緩存

個(gè)人理解的緩存是指用于存儲(chǔ)頻繁使用的數(shù)據(jù)的空間,關(guān)注點(diǎn)是存儲(chǔ)數(shù)據(jù)的空間和使用頻繁的數(shù)據(jù)。緩存技術(shù),簡(jiǎn)單的說就是先從緩存中查詢數(shù)據(jù)是否存在,存在則直接返回,不存在再執(zhí)行相應(yīng)的操作獲取數(shù)據(jù),并將獲取的數(shù)據(jù)存儲(chǔ)到緩存中,它是一種提升系統(tǒng)性能的重要方法。

1.Redis

Redis是一個(gè)開源的、內(nèi)存存儲(chǔ)key-value類型的數(shù)據(jù)結(jié)構(gòu)服務(wù)器,可用作數(shù)據(jù)庫、高速緩存和消息隊(duì)列代理。它支持的數(shù)據(jù)類型有字符串、哈希表、列表、集合、有序集合等,同時(shí)通過Redis Sentinel提供高可用,通過Redis Cluster提供分區(qū)功能。

2.jedis

jedis是Redis的Java版客戶端實(shí)現(xiàn),也是官方推薦的Java版客戶端。它封裝了對(duì)Redis的各種操作,并且支持事務(wù)、管道及有jedis自身實(shí)現(xiàn)的分布式。

3.Spring Data Redis

Spring Data是Spring框架中的一個(gè)主要項(xiàng)目,目的是為了簡(jiǎn)化構(gòu)建基于Spring框架應(yīng)用的數(shù)據(jù)訪問,包括非關(guān)系數(shù)據(jù)庫、Map-Reduce框架、云數(shù)據(jù)服務(wù)等,另外也包含對(duì)關(guān)系數(shù)據(jù)庫的訪問支持。
Spring Data Redis是Spring Data項(xiàng)目中的一個(gè)主要模塊,實(shí)現(xiàn)了對(duì)jedis客戶端API的高度封裝,使對(duì)Redis的操作更加便捷。

4.關(guān)系圖

Redis、jedis、Spring Data Redis三者之間的關(guān)系圖如下所示。

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

5.Spring Cache

從Spring3.1開始,Spring框架提供了對(duì)Cache的支持,提供了一個(gè)對(duì)緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達(dá)到緩存方法的返回對(duì)象的作用。提供的主要注解有@Cacheable、@CachePut、@CacheEvict和@Caching,具體見表1。

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

@Cacheable的常用屬性及說明如表2所示。

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

@CacheEvict的常用屬性見表4。@CachePut的常用屬性同@Cacheable。

使用Spring Data Redis實(shí)現(xiàn)數(shù)據(jù)緩存的方法

當(dāng)需要在類上或方法上同時(shí)使用多個(gè)注解時(shí),可以使用@Caching,如@Caching(cacheable = @Cacheable("User"), evict = {@CacheEvict("Member"), @CacheEvict(value = "Customer", allEntries = true)})

6.使用示例

下面使用Spring Data Reds、Redis和jedis實(shí)現(xiàn)一個(gè)簡(jiǎn)單的數(shù)據(jù)緩存。

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實(shí)例 -->
  <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)測(cè)試

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

    System.out.println("第二次執(zhí)行查詢:" + 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("修改數(shù)據(jù)后查詢:" + userService.queryFullNameById(110L));
    System.out.println("----------------------------------");

    System.out.println("第一次執(zhí)行查詢:" + userService.queryFullNameById(112L));
    System.out.println("----------------------------------");

    System.out.println("第二次執(zhí)行查詢:" + userService.queryFullNameById(112L));
    System.out.println("----------------------------------");
  }

6)測(cè)試結(jié)果

輸出結(jié)果如下。

execute queryFullNameById method
第一次執(zhí)行查詢:ZhangSanFeng
----------------------------------
第二次執(zhí)行查詢:ZhangSanFeng
----------------------------------
execute deleteById method
----------------------------------
execute queryFullNameById method
清除緩存后查詢:ZhangSanFeng
----------------------------------
execute modifyFullNameById method
ZhangJunBao
----------------------------------
修改數(shù)據(jù)后查詢:ZhangJunBao
----------------------------------
execute queryFullNameById method
第一次執(zhí)行查詢:ZhangSanFeng
----------------------------------
execute queryFullNameById method
第二次執(zhí)行查詢:ZhangSanFeng
----------------------------------

從結(jié)果可以看到,使用緩存后,第二次查詢沒有執(zhí)行查詢方法體,直接返回了緩存中的數(shù)據(jù);清除緩存后,再次查詢就執(zhí)行了查詢方法體;修改數(shù)據(jù)后,相應(yīng)的緩存數(shù)據(jù)也被修改了;不符合緩存條件的數(shù)據(jù)沒有被緩存。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI