Spring從3.1開始仰冠,Spring引入了對Cache的支持蜕依,其使用方法和原理都類似于Spring對事務(wù)管理的支持典勇,Spring Cache是作用在方法上劫哼。核心思想,調(diào)用一個緩存方法時會把該方法的參數(shù)和返回值作為一組鍵值對存放在緩存中割笙,下次使用相同的參數(shù)來調(diào)用該方法時將直接讀取緩存中的內(nèi)容权烧。
SpringBoot提供了對Redis集成的組件包spring-boot-starter-data-redis(不要依賴spring-boot-starter-redis,他是舊版本)伤溉,該組件包同時依賴于spring-data-redis和lettuce般码,SpringBoot1.0默認(rèn)使用Jedis客戶端,2.0替換成了Lettuce乱顾。
Jedis在實現(xiàn)上是直連Redis服務(wù)板祝,多線程環(huán)境下非線程安全,除非使用連接池走净,為每個RedisConnection實例增加物理連接扔字。
Lettuce是一個可伸縮非阻塞且線程安全的Redis客戶端囊嘉,多個線程可以共享同一個RedisConnection温技,它利用netty NIO框架來高效地管理多個連接革为。
本文主要介紹Docker下安裝Redis、SpringBoot集成Redis以及具體的應(yīng)用分布式Session
Docker安裝Redis
鏡像選取
可通過DockerHub或者命令行選取鏡像舵鳞,Docker的安裝可參考Docker安裝
DockerHub選取
訪問https://hub.docker.com搜索redis即可震檩,https://hub.docker.com/search?q=redis&type=image
命令行選取
一般選取Starts最多的官方鏡像
docker search redis
可以查看到如下內(nèi)容(只截取了前三個)
kk@kk demo $ docker search redis
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redis Redis is an open source key-value store that… 7926 [OK]
bitnami/redis Bitnami Redis Docker Image 138 [OK]
sameersbn/redis 79 [OK]
拉取鏡像
默認(rèn)拉取最新版本的鏡像
docker pull redis
啟動容器
查看鏡像
docker images
可以查看到IMAGE ID(鏡像ID)
創(chuàng)建容器
docker run --name myredis -p 6379:6379 -d redis redis-server --appendonly yes
- --name 設(shè)置命名(myredis)
- -p 映射宿主機(jī)端口到容器端口
- -d 后臺以守護(hù)進(jìn)程方式運行
- redis 鏡像名(或者替換成鏡像ID均可)
- redis-server --appendonly yes 在容器啟動執(zhí)行redis-server命令,打開redis持久化
查看容器
執(zhí)行命令蜓堕,查看正在運行的容器抛虏,可以觀察到已正常啟動
docker ps
啟動成功后顯示如下
kk@kk demo $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
038d4475783a redis "docker-entrypoint.s…" 7 seconds ago Up 5 seconds 0.0.0.0:6379->6379/tcp myredis
查看容器日志
docker logs -f 038d4475783a
注意 038d4475783a 需替換成自己的redis容器ID
可以查看到以綁定6379端口
kk@kk demo $ docker logs -f 038d4475783a
1:C 18 Mar 2020 03:08:29.408 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 18 Mar 2020 03:08:29.408 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 18 Mar 2020 03:08:29.408 # Configuration loaded
1:M 18 Mar 2020 03:08:29.409 * Running mode=standalone, port=6379.
1:M 18 Mar 2020 03:08:29.409 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 18 Mar 2020 03:08:29.409 # Server initialized
1:M 18 Mar 2020 03:08:29.410 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:M 18 Mar 2020 03:08:29.410 * Ready to accept connections
SpringBoot集成Redis
簡易項目實戰(zhàn)
pom添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件application
server:
port: 8078
spring:
application:
name: redis-session
cache:
type: redis
# redis 配置
redis:
# 服務(wù)器地址
host: 127.0.0.1
# 服務(wù)器端口
port: 6379
# 服務(wù)器連接密碼(默認(rèn)為空)
password:
# Redis分片(默認(rèn)有16個分片,默認(rèn)為0)套才,在大型項目中建議使用0號分片存儲迂猴,select分片耗時較大
database: 0
# 連接超時時間
timeout: 1000ms
redis簡易使用
private final String cacheKey = "redis:cache:key:userid";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("/stringset")
public String stringSetAction(@RequestParam String key, @RequestParam String value) {
stringRedisTemplate.opsForValue().set(key, value);
return stringRedisTemplate.opsForValue().get(key);
}
基于注解的Redis
使用Spring Cache主要包含兩個步驟,
- 聲明某些方法使用緩存
- 配置Spring對Cache的支持
和Spring對事務(wù)管理的支持一樣背伴,Spring對Cache的支持也有基于注解和基于XML配置兩種方式沸毁,以下將以注解方式進(jìn)行驗證
常用注解
@EnableCaching
開啟緩存功能,一般放在啟動類或者Redis的配置類上
@Cacheable
@Cacheable可以標(biāo)記在方法上傻寂,也可以標(biāo)記在類上息尺。當(dāng)標(biāo)記在方法上時表示該方法是支持緩存的,當(dāng)標(biāo)記在類上時表示該類所有的方法都支持緩存疾掰。
對于一個支持緩存的方法搂誉,Spring會在其被調(diào)用后將其返回值緩存起來,以保證下次使用相同的參數(shù)調(diào)用該方法時静檬,直接返回緩存中的結(jié)果炭懊。支持緩存的方法在對象內(nèi)部被調(diào)用時不會觸發(fā)緩存功能
Spring緩存方法的返回值是以鍵值對進(jìn)行緩存的,值就是方法的返回結(jié)果拂檩,對于鍵侮腹,Spring支持兩種策略,默認(rèn)策略和自定義策略广恢。
@Cacheable可以設(shè)置如下屬性
- value:緩存名稱(必填)凯旋,指定緩存的命名空間
- key:用于設(shè)置在命名空間中的緩存key值,可以使用SpEL表達(dá)式定義
- unless:條件符合則不緩存
- condition:條件符合則緩存
@CachePut
@CachePut也可以聲明一個方法支持緩存功能钉迷,與@Cacheable不同的是使用@CachePut標(biāo)注的方法在執(zhí)行前不會去檢查緩存中是否存在之前執(zhí)行的結(jié)果至非,而是每次都會執(zhí)行該方法,并將執(zhí)行結(jié)果以鍵值對的形式存入指定的緩存中
@CachePut可以設(shè)置如下屬性
- value:緩存名稱(必填)糠聪,指定緩存的命名空間
- key:用于設(shè)置在命名空間中的緩存key值荒椭,可以使用SpEL表達(dá)式定義
- unless:條件符合則不緩存
- condition:條件符合則緩存
@CacheEvict
@CacheEvict可以標(biāo)記在方法上,也可以標(biāo)記在類上舰蟆,當(dāng)標(biāo)記在一個類上時表示其中所有的方法的執(zhí)行都會觸發(fā)緩存的清除操作趣惠,
@CacheEvict可以設(shè)置如下屬性
- value:緩存名稱(必填)狸棍,指定緩存的命名空間
- key:用于設(shè)置在命名空間中的緩存key值,可以使用SpEL表達(dá)式定義
- condition:條件符合則緩存
基于注解的項目實戰(zhàn)
pom添加依賴
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
@Cacheable使用
注意:需要使用瀏覽器或postman進(jìn)行驗證味悄,使用IDEA插件RestService調(diào)用緩存不會生效
private final String cacheKey = "redis:cache:key:userid";
@RequestMapping("/cache")
@Cacheable(value = cacheKey)
public String cacheIndex() {
System.out.println("set cache");
return "set cache";
}
只有首次訪問的時候再控制臺打印“set cache”草戈,之后直接返回Redis結(jié)果,不會在控制臺打印信息了
@CachePut使用
private final String cacheKey = "redis:cache:key:userid";
@RequestMapping("/put")
@CachePut(value = cacheKey)
public String putAction() {
System.out.println("update cache");
return "update cache";
}
每次訪問會更新為本次的返回值
@CacheEvict使用
private final String cacheKey = "redis:cache:key:userid";
@RequestMapping("/del")
@CacheEvict(value = cacheKey)
public String delAction() {
System.out.println("delete cache");
return "delete cache";
}
刪除緩存的內(nèi)容
共享Session
分布式系統(tǒng)中侍瑟,Session共享有很多解決方案唐片,存儲到緩存中是最常用的方案之一
Spring Session提供了一套創(chuàng)建和管理Servlet HttpSession的方案。Spring Session提供了集群Session(Clustered Sessions)功能涨颜,默認(rèn)采用外置的Redis來存儲Session數(shù)據(jù)费韭,以此來解決Session共享問題
Session項目實戰(zhàn)
pom依賴
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
Session配置文件
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}
maxInactiveIntervalInSeconds:設(shè)置Session失效時間,使用Redis Session之后庭瑰,Spring Boot配置文件中的server.session.timeout屬性將不再生效
測試-獲取sessionID
注意:需要使用瀏覽器或postman進(jìn)行驗證星持,使用IDEA插件RestService調(diào)用緩存不會生效
@RestController
@RequestMapping("/session")
public class RedisSessionController {
@RequestMapping("/uid")
public String sessionAction(HttpSession session) {
UUID uid = (UUID) session.getAttribute("uid");
System.out.println("get " + uid);
if (uid == null) {
System.out.println("start set " + uid);
uid = UUID.randomUUID();
}
System.out.println("set " + uid);
session.setAttribute("uid", uid);
return session.getId();
}
}
可以多次調(diào)用觀察控制臺的打印信息