更多Spring文章,歡迎點擊 一灰灰Blog-Spring專題
在Spring的應用中,redis可以算是基礎操作了。那麼想要玩轉redis,我們需要知道哪些知識點呢?
- redis配置,默認,非默認,集羣,多實例,連接池參數等
- redis讀寫操作,RedisTemplate的基本使用姿勢
- 幾種序列化方式對比
本篇博文爲redis系列的開篇,將介紹最基本的配置
原文鏈接: 181029-SpringBoot高級篇Redis之基本配置
I. redis基本配置
1. 默認配置
最簡單的使用其實開箱即可用,添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
本機啓動redis,一切採用默認的配置 (host:127.0.0.1, port:6379, 無密碼)
然後就可以愉快的玩耍了,可以直接注入redisTemplate
實例,進行各種讀寫操作
@SpringBootApplication
public class Application {
public Application(RedisTemplate<String, String> redisTemplate) {
redisTemplate.opsForValue().set("hello", "world");
String ans = redisTemplate.opsForValue().get("hello");
Assert.isTrue("world".equals(ans));
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. 自定義配置參數
前面是默認的配置參數,在實際的使用中,一般都會修改這些默認的配置項,如果我的應用中,只有一個redis,那麼完全可以只修改默認的配置參數
修改配置文件: application.yml
spring:
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
lettuce:
pool:
max-active: 32
max-wait: 300ms
max-idle: 16
min-idle: 8
使用和前面沒有什麼區別,直接通過注入RedisTemplate
來操作即可,需要額外注意的是設置了連接池的相關參數,需要額外引入依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
3. 多redis配置
依賴多個不同的redis,也就是說我的項目需要從多個redis實例中獲取數據,這種時候,就不能直接使用默認的,需要我們自己來聲明ConnectionFactory
和 RedisTemplate
配置如下
spring:
redis:
host: 127.0.0.1
port: 6379
password:
lettuce:
pool:
max-active: 32
max-wait: 300
max-idle: 16
min-idle: 8
database: 0
local-redis:
host: 127.0.0.1
port: 6379
database: 0
password:
lettuce:
pool:
max-active: 16
max-wait: 100
max-idle: 8
min-idle: 4
對應的配置類,採用Lettuce,基本設置如下,套路都差不多,先讀取配置,初始化ConnectionFactory
,然後創建RedisTemplate
實例,設置連接工廠
@Configuration
public class RedisAutoConfig {
@Bean
public LettuceConnectionFactory defaultLettuceConnectionFactory(RedisStandaloneConfiguration defaultRedisConfig,
GenericObjectPoolConfig defaultPoolConfig) {
LettuceClientConfiguration clientConfig =
LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100))
.poolConfig(defaultPoolConfig).build();
return new LettuceConnectionFactory(defaultRedisConfig, clientConfig);
}
@Bean
public RedisTemplate<String, String> defaultRedisTemplate(
LettuceConnectionFactory defaultLettuceConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(defaultLettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
@ConditionalOnBean(name = "localRedisConfig")
public LettuceConnectionFactory localLettuceConnectionFactory(RedisStandaloneConfiguration localRedisConfig,
GenericObjectPoolConfig localPoolConfig) {
LettuceClientConfiguration clientConfig =
LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100))
.poolConfig(localPoolConfig).build();
return new LettuceConnectionFactory(localRedisConfig, clientConfig);
}
@Bean
@ConditionalOnBean(name = "localLettuceConnectionFactory")
public RedisTemplate<String, String> localRedisTemplate(LettuceConnectionFactory localLettuceConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(localLettuceConnectionFactory);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Configuration
@ConditionalOnProperty(name = "host", prefix = "spring.local-redis")
public static class LocalRedisConfig {
@Value("${spring.local-redis.host:127.0.0.1}")
private String host;
@Value("${spring.local-redis.port:6379}")
private Integer port;
@Value("${spring.local-redis.password:}")
private String password;
@Value("${spring.local-redis.database:0}")
private Integer database;
@Value("${spring.local-redis.lettuce.pool.max-active:8}")
private Integer maxActive;
@Value("${spring.local-redis.lettuce.pool.max-idle:8}")
private Integer maxIdle;
@Value("${spring.local-redis.lettuce.pool.max-wait:-1}")
private Long maxWait;
@Value("${spring.local-redis.lettuce.pool.min-idle:0}")
private Integer minIdle;
@Bean
public GenericObjectPoolConfig localPoolConfig() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWait);
return config;
}
@Bean
public RedisStandaloneConfiguration localRedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPassword(RedisPassword.of(password));
config.setPort(port);
config.setDatabase(database);
return config;
}
}
@Configuration
public static class DefaultRedisConfig {
@Value("${spring.redis.host:127.0.0.1}")
private String host;
@Value("${spring.redis.port:6379}")
private Integer port;
@Value("${spring.redis.password:}")
private String password;
@Value("${spring.redis.database:0}")
private Integer database;
@Value("${spring.redis.lettuce.pool.max-active:8}")
private Integer maxActive;
@Value("${spring.redis.lettuce.pool.max-idle:8}")
private Integer maxIdle;
@Value("${spring.redis.lettuce.pool.max-wait:-1}")
private Long maxWait;
@Value("${spring.redis.lettuce.pool.min-idle:0}")
private Integer minIdle;
@Bean
public GenericObjectPoolConfig defaultPoolConfig() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(maxActive);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWait);
return config;
}
@Bean
public RedisStandaloneConfiguration defaultRedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPassword(RedisPassword.of(password));
config.setPort(port);
config.setDatabase(database);
return config;
}
}
}
測試類如下,簡單的演示下兩個template的讀寫
@SpringBootApplication
public class Application {
public Application(RedisTemplate<String, String> localRedisTemplate, RedisTemplate<String, String>
defaultRedisTemplate)
throws InterruptedException {
// 10s的有效時間
localRedisTemplate.delete("key");
localRedisTemplate.opsForValue().set("key", "value", 100, TimeUnit.MILLISECONDS);
String ans = localRedisTemplate.opsForValue().get("key");
System.out.println("value".equals(ans));
TimeUnit.MILLISECONDS.sleep(200);
ans = localRedisTemplate.opsForValue().get("key");
System.out.println("value".equals(ans) + " >> false ans should be null! ans=[" + ans + "]");
defaultRedisTemplate.opsForValue().set("key", "value", 100, TimeUnit.MILLISECONDS);
ans = defaultRedisTemplate.opsForValue().get("key");
System.out.println(ans);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
上面的代碼執行演示如下
上面的演示爲動圖,抓一下重點:
- 注意
localRedisTemplate
,defaultRedisTemplate
兩個對象不相同(看debug窗口後面的@xxx
) - 同樣兩個
RedisTemplate
的ConnectionFactory
也是兩個不同的實例(即分別對應前面配置類中的兩個Factory) -
執行後輸出的結果正如我們預期的redis操作
- 塞值,馬上取出沒問題
- 失效後,再查詢,返回null
- 最後輸出異常日誌,提示如下
Description:
Parameter 0 of method redisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration required a single bean, but 2 were found:
- defaultLettuceConnectionFactory: defined by method 'defaultLettuceConnectionFactory' in class path resource [com/git/hui/boot/redis/config/RedisAutoConfig.class]
- localLettuceConnectionFactory: defined by method 'localLettuceConnectionFactory' in class path resource [com/git/hui/boot/redis/config/RedisAutoConfig.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
上面表示說有多個ConnectionFactory存在,然後創建默認的RedisTemplate就不知道該選擇哪一個了,有兩種方法
方法一:指定默認的ConnectionFactory
藉助@Primary
來指定默認的連接工廠,然後在使用工程的時候,通過@Qualifier
註解來顯示指定,我需要的工廠是哪個(主要是localRedisTemplate
這個bean的定義,如果不加,則會根據defaultLettuceConnectionFactory
這個實例來創建Redis連接了)
@Bean
@Primary
public LettuceConnectionFactory defaultLettuceConnectionFactory(RedisStandaloneConfiguration defaultRedisConfig,
GenericObjectPoolConfig defaultPoolConfig) {
// ...
}
@Bean
public RedisTemplate<String, String> defaultRedisTemplate(
@Qualifier("defaultLettuceConnectionFactory") LettuceConnectionFactory defaultLettuceConnectionFactory) {
// ....
}
@Bean
@ConditionalOnBean(name = "localRedisConfig")
public LettuceConnectionFactory localLettuceConnectionFactory(RedisStandaloneConfiguration localRedisConfig,
GenericObjectPoolConfig localPoolConfig) {
// ...
}
@Bean
@ConditionalOnBean(name = "localLettuceConnectionFactory")
public RedisTemplate<String, String> localRedisTemplate(
@Qualifier("localLettuceConnectionFactory") LettuceConnectionFactory localLettuceConnectionFactory) {
// ...
}
方法二:忽略默認的自動配置類
既然提示的是org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
類加載bean衝突,那麼就不加載這個配置即可
@SpringBootApplication
@EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class})
public class Application {
// ...
}
II. 其他
0. 項目
- 工程:spring-boot-demo
- module: 120-redis-config
1. 一灰灰Blog
- 一灰灰Blog個人博客 https://blog.hhui.top
- 一灰灰Blog-Spring專題博客 http://spring.hhui.top
一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 聲明
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog
知識星球