Spring Boot整合Redis叢集(Cluster模式)

Acelin_H發表於2021-08-30

同樣的,我們還是分兩種整合方式來介紹,並是以Cluster模式進行整合。另外,還有幾篇關於的Windows下Redis的搭建與整合系列文章可做參考

Spring Boot 專案整合Redis

windows下Redis的安裝和使用

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分別呼叫setDatagetData對應服務,控制檯列印以下資訊:

image

用redis-cli客戶端連線叢集中任意一個節點

redis-cli -c -p 7001

得到叢集中已經有相關記錄:

image


整合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);
    }
}

使用

編寫對應的setget服務

@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分別呼叫setDatagetData對應服務,控制檯列印以下資訊:

image

用redis-cli客戶端連線叢集中任意一個節點

redis-cli -c -p 7006

得到叢集中已經有相關記錄:

image


異常處理


io.lettuce.core.RedisConnectionException: Connection closed prematurely

redis啟動配置中預設是有保護模式的,要關閉保護模式


相關文章