使用Spring Data Redis實現(xiàn)數(shù)據(jù)緩存的方法
引言
目前很多系統(tǒng)為了解決數(shù)據(jù)讀寫的性能瓶頸,在系統(tǒng)架構(gòu)設(shè)計中使用Redis實現(xiàn)緩存,Spring框架為了讓開發(fā)人員更加方便快捷的使用Redis實現(xiàn)緩存,對Redis的操作進(jìn)行了包裝。
0.緩存
個人理解的緩存是指用于存儲頻繁使用的數(shù)據(jù)的空間,關(guān)注點是存儲數(shù)據(jù)的空間和使用頻繁的數(shù)據(jù)。緩存技術(shù),簡單的說就是先從緩存中查詢數(shù)據(jù)是否存在,存在則直接返回,不存在再執(zhí)行相應(yīng)的操作獲取數(shù)據(jù),并將獲取的數(shù)據(jù)存儲到緩存中,它是一種提升系統(tǒng)性能的重要方法。
1.Redis
Redis是一個開源的、內(nèi)存存儲key-value類型的數(shù)據(jù)結(jié)構(gòu)服務(wù)器,可用作數(shù)據(jù)庫、高速緩存和消息隊列代理。它支持的數(shù)據(jù)類型有字符串、哈希表、列表、集合、有序集合等,同時通過Redis Sentinel提供高可用,通過Redis Cluster提供分區(qū)功能。
2.jedis
jedis是Redis的Java版客戶端實現(xiàn),也是官方推薦的Java版客戶端。它封裝了對Redis的各種操作,并且支持事務(wù)、管道及有jedis自身實現(xiàn)的分布式。
3.Spring Data Redis
Spring Data是Spring框架中的一個主要項目,目的是為了簡化構(gòu)建基于Spring框架應(yīng)用的數(shù)據(jù)訪問,包括非關(guān)系數(shù)據(jù)庫、Map-Reduce框架、云數(shù)據(jù)服務(wù)等,另外也包含對關(guān)系數(shù)據(jù)庫的訪問支持。
Spring Data Redis是Spring Data項目中的一個主要模塊,實現(xiàn)了對jedis客戶端API的高度封裝,使對Redis的操作更加便捷。
4.關(guān)系圖
Redis、jedis、Spring Data Redis三者之間的關(guān)系圖如下所示。
5.Spring Cache
從Spring3.1開始,Spring框架提供了對Cache的支持,提供了一個對緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達(dá)到緩存方法的返回對象的作用。提供的主要注解有@Cacheable、@CachePut、@CacheEvict和@Caching,具體見表1。
@Cacheable的常用屬性及說明如表2所示。
@CacheEvict的常用屬性見表4。@CachePut的常用屬性同@Cacheable。
當(dāng)需要在類上或方法上同時使用多個注解時,可以使用@Caching,如@Caching(cacheable = @Cacheable("User"), evict = {@CacheEvict("Member"), @CacheEvict(value = "Customer", allEntries = true)})
6.使用示例
下面使用Spring Data Reds、Redis和jedis實現(xià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實例 --> <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("第一次執(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)測試結(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ù)沒有被緩存。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解讀springboot配置mybatis的sql執(zhí)行超時時間(mysql)
這篇文章主要介紹了解讀springboot配置mybatis的sql執(zhí)行超時時間(mysql),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01java編程創(chuàng)建型設(shè)計模式單例模式的七種示例
這篇文章主要為大家介紹了java編程中創(chuàng)建型設(shè)計模式之單例模式的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02idea創(chuàng)建javaweb原生項目的實現(xiàn)示例
這篇文章主要介紹了idea創(chuàng)建javaweb原生項目的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Java實現(xiàn)動態(tài)獲取圖片驗證碼的示例代碼
這篇文章主要介紹了Java實現(xiàn)動態(tài)獲取圖片驗證碼的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08SpringBoot/Spring?AOP默認(rèn)動態(tài)代理方式實例詳解
這篇文章主要給大家介紹了關(guān)于SpringBoot/Spring?AOP默認(rèn)動態(tài)代理方式的相關(guān)資料,Spring AOP是一款基于Java的AOP框架,其中默認(rèn)采用動態(tài)代理方式實現(xiàn)AOP功能,本文將詳細(xì)介紹動態(tài)代理的實現(xiàn)原理和使用方法,需要的朋友可以參考下2023-03-03