引言
目前很多系統為了解決數據讀寫的性能瓶頸,在系統架構設計中使用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三者之間的關系圖如下所示。
5.spring cache
從spring3.1開始,spring框架提供了對cache的支持,提供了一個對緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達到緩存方法的返回對象的作用。提供的主要注解有@cacheable、@cacheput、@cacheevict和@caching,具體見表1。
@cacheable的常用屬性及說明如表2所示。
@cacheevict的常用屬性見表4。@cacheput的常用屬性同@cacheable。
當需要在類上或方法上同時使用多個注解時,可以使用@caching,如@caching(cacheable = @cacheable("user"), evict = {@cacheevict("member"), @cacheevict(value = "customer", allentries = true)})
6.使用示例
下面使用spring data reds、redis和jedis實現一個簡單的數據緩存。
1)依賴配置
示例使用了gradle,所以需要在build.gradle中加入如下依賴配置來管理所需要的jar。
1
2
3
|
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配置如下。
1
2
3
4
5
6
7
8
9
10
|
# 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的配置文件如下。
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
|
<?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如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@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)測試
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
|
@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