Spring Boot集成Redis集群(Cluster模式)
- 2021 年 8 月 30 日
- 筆記
- Redis, springboot
同樣的,我們還是分兩種集成方式來介紹,並是以Cluster模式進行集成。另外,還有幾篇關於的Windows下Redis的搭建與集成系列文章可做參考
集成jedis
引入依賴
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
配置綁定
新增配置
################################################ 連接池配置
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.pool.max-active=100
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=2000
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=500
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=0
################################################ redis集群部署配置
#設置key的生存時間,當key過期時,它會被自動刪除
spring.redis.cluster.expire-seconds=120
#設置redis集群的節點信息
spring.redis.cluster.nodes=127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006
#設置命令的執行時間,如果超過這個時間,則報錯
spring.redis.cluster.command-timeout=5000
新增對應配置映射類RedisPoolProperties
@Component
@PropertySource("classpath:/redis.properties")
public class RedisPoolProperties {
private Integer maxActive;
private Integer maxWait;
private Integer maxIdle;
private Integer minIdle;
public Integer getMaxActive() {
return maxActive;
}
public void setMaxActive(Integer maxActive) {
this.maxActive = maxActive;
}
public Integer getMaxWait() {
return maxWait;
}
public void setMaxWait(Integer maxWait) {
this.maxWait = maxWait;
}
public Integer getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(Integer maxIdle) {
this.maxIdle = maxIdle;
}
public Integer getMinIdle() {
return minIdle;
}
public void setMinIdle(Integer minIdle) {
this.minIdle = minIdle;
}
@Override
public String toString() {
return "RedisPoolProperties{" +
"maxActive=" + maxActive +
", maxWait=" + maxWait +
", maxIdle=" + maxIdle +
", minIdle=" + minIdle +
'}';
}
}
連接池的配置的在上一篇文章Spring Boot 項目集成Redis已做介紹
註冊
拿到集群的相關配置,然後就集群的註冊
@Configuration
public class RedisConfig {
@Autowired
private RedisClusterProperties redisClusterProperties;
/* Jedis - 集群、連接池模式 */
@Bean
public JedisCluster jedisCluster(){
/* 切割節點信息 */
String[] nodes = redisClusterProperties.getNodes().split(",");
Set<HostAndPort> hostAndPorts = new HashSet<>();
for (String node : nodes) {
int index = node.indexOf(":");
hostAndPorts.add(new HostAndPort(node.substring(0,index),Integer.parseInt(node.substring(index + 1))));
}
/* Jedis連接池配置 */
JedisPoolConfig jedisPoolConfig = getJedisPoolConfig();
return new JedisCluster(hostAndPorts,redisClusterProperties.getCommandTimeout(),jedisPoolConfig);
}
/**
* 連接池配置
* @return JedisPoolConfig
**/
private JedisPoolConfig getJedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(redisPoolProperties.getMaxIdle()); // 最大空閑連接數, 默認8個
jedisPoolConfig.setMaxTotal(redisPoolProperties.getMaxActive()); // 最大連接數, 默認8個
jedisPoolConfig.setMinIdle(redisPoolProperties.getMinIdle()); // 最小空閑連接數, 默認0
jedisPoolConfig.setMaxWaitMillis(redisPoolProperties.getMaxWait()); // 獲取連接時的最大等待毫秒數(如果設置為阻塞時BlockWhenExhausted),如果超時就拋異常, 小於零:阻塞不確定的時間, 默認-1
jedisPoolConfig.setTestOnBorrow(true); // 對拿到的connection進行validateObject校驗
return jedisPoolConfig;
}
}
獲取redis客戶端
新增一個工具接口IRedisCluster
,然後寫一個組件對接口進行實現:獲取redis客戶端實例後,進行redis相關操作的封裝
接口
public interface IRedisCluster {
String set(String key, String value);
String get(String key);
}
實現IRedisCluster
接口
@Service("redisClusterService")
public class RedisClusterService implements IRedisCluster{
@Autowired
private JedisCluster jedisCluster;
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
}
先封裝兩個最簡單的方法,更詳細的封裝後續再介紹
使用
新增一個RedisController
編寫簡單的服務接口:
@RestController
public class RedisClusterController {
@Autowired
@Qualifier("redisClusterService")
private IRedisCluster redisCluster;
@PostMapping("/cluster/jedis/{key}")
public void setDataByJedis(@PathVariable("key") String key){
System.out.println("set " + key);
redisCluster.set(key,key + "nice");
}
@GetMapping("/cluster/jedis/{key}")
public void getDataByJedis(@PathVariable("key") String key){
System.out.println(redisCluster.get(key));
}
}
驗證
用postman分別調用setData
和getData
對應服務,控制台打印以下信息:
用redis-cli客戶端連接集群中任意一個節點
redis-cli -c -p 7001
得到集群中已經有相關記錄:
集成spring-data-redis
引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置綁定
因為是Spring封裝的組件,所以有比較完善的支持,我們直接在“下新增關於集群的配置
# ------------------------------------------------------------ cluster集群模式
# 重連最大數
spring.redis.cluster.max-redirects=3
# 集群主機信息
spring.redis.cluster.nodes=127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005,127.0.0.1:7006
# ------------------------------------------------------------ 連接池配置
# lettuce
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.min-idle=0
- 配置spring.redis.lettuce.pool節點會自動你開啟連接池
- 需將單機模式的相關配置注釋掉,不然雖然能啟動,但的操作redis時會報錯
註冊
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
/* 設置value的序列化規則和 key的序列化規則 */
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer); // key採用String的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer); // hash的key也採用String的序列化方式
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer); // value序列化方式採用jackson
redisTemplate.setConnectionFactory(connectionFactory); // 默認使用letttuce,如果想使用Jedis,創建JedisConnectionFactory實例作為參數傳入
return redisTemplate;
}
}
獲取redis客戶端
同樣實現的上述的IRedisCluster
接口
@Service("redisClusterTemplateService")
public class RedisClusterTemplateService implements IRedisCluster{
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public String set(String key, String value) {
redisTemplate.opsForValue().set(key,value);
return key;
}
@Override
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
使用
編寫對應的set
和get
服務
@RestController
public class RedisClusterController {
@Autowired
@Qualifier("redisClusterTemplateService")
private IRedisCluster redisTemplateCluster;
@PostMapping("/cluster/{key}")
public void setData(@PathVariable("key") String key){
System.out.println("set " + key);
redisTemplateCluster.set(key,key + " nice");
}
@GetMapping("/cluster/{key}")
public void getData(@PathVariable("key") String key){
System.out.println(redisTemplateCluster.get(key));
}
}
驗證
用postman分別調用setData
和getData
對應服務,控制台打印以下信息:
用redis-cli客戶端連接集群中任意一個節點
redis-cli -c -p 7006
得到集群中已經有相關記錄:
異常處理
io.lettuce.core.RedisConnectionException: Connection closed prematurely
redis啟動配置中默認是有保護模式的,要關閉保護模式