1. 程式人生 > 程式設計 >SpringBoot2.X整合Redis(單機+叢集+多資料來源)-Lettuce版

SpringBoot2.X整合Redis(單機+叢集+多資料來源)-Lettuce版

最近專案嘗試從SpringBoot1.X升級到SpringBoot2.X,但是 Spring Boot 2.0中 Redis 客戶端驅動現在由 Jedis變為了 Lettuce,所以嘗試測試一下Lettuce的使用. 下面簡單介紹一下Lettuce.

Redis 三大客戶端

簡介

Jedis:是Redis 老牌的Java實現客戶端,提供了比較全面的Redis命令的支援,

Redisson:實現了分散式和可擴充套件的Java資料結構。

Lettuce:高階Redis客戶端,用於執行緒安全同步,非同步和響應使用,支援叢集,Sentinel,管道和編碼器。

優點:

Jedis:比較全面的提供了Redis的操作特性

Redisson:促使使用者對Redis的關注分離,提供很多分散式相關操作服務,例如分散式鎖,分散式集合,可通過Redis支援延遲佇列

Lettuce:主要在一些分散式快取框架上使用比較多

可伸縮:

Jedis:使用阻塞的I/O,且其方法呼叫都是同步的,程式流需要等到sockets處理完I/O才能執行,不支援非同步。Jedis客戶端例項不是執行緒安全的,所以需要通過連線池來使用Jedis

Redisson:基於Netty框架的事件驅動的通訊層,其方法呼叫是非同步的。Redisson的API是執行緒安全的,所以可以操作單個Redisson連線來完成各種操作

Lettuce:基於Netty框架的事件驅動的通訊層,其方法呼叫是非同步的。Lettuce的API是執行緒安全的,所以可以操作單個Lettuce連線來完成各種操作

pipeline 的支援

jedis 通過一定的改造後可以支援pipeline,具體可以看 Redis 批量操作之 pipeline

但是 Lettuce 的pipeline行為很奇怪. 在 Spring RedisTemplate 中的 executePipelined 方法中的情況:

有時完全是一條一條命令地傳送

有時全合併幾條命令傳送

但跟完全 pipeline 的方式不同,測試多次,但沒發現有一次是完整 pipeline 的
複製程式碼

所以如果需要使用pipeline的話,建議還是使用Jedis

Lettuce 接入

單機版

配置檔案

    host: 192.168.131
.118 port: 4884 password: dsgs548 database: 0 # lettuce簡單配置 lettuce: pool: # 最大活躍連結數 預設8 max-active: 5 # 最大空閒連線數 預設8 max-idle: 10 # 最小空閒連線數 預設0 min-idle: 0 複製程式碼

redis配置類

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key採用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也採用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式採用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式採用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}
複製程式碼

直接引入RedisTemplate 即可,單機版比較簡單

叢集版+多資料來源

配置檔案

spring:
  redis:
    cluster:
      nodes: 192.168.131.118:4883,192.168.131.118:4884,192.168.131.118:4885
#      nodes:
#        - 192.168.131.118:4883
#        - 1192.168.131.118:4884
#        - 192.168.131.118:4885
    password: adfafsas
    lettuce:
      pool:
        # 最大活躍連結數 預設8
        max-active: 5
        # 最大空閒連線數 預設8
        max-idle: 10
        # 最小空閒連線數 預設0
        min-idle: 0
  secondaryRedis:
    cluster:
      nodes: 192.168.131.118:4883,192.168.131.118:4885
#      nodes:
#        - 192.168.131.118:4883
#        - 192.168.131.118:4884
#        - 192.168.131.118:4885
    password: advfafasfsa
複製程式碼

redis配置類

@Configuration
public class RedisConfig {

    @Autowired
    private Environment environment;
    /**
     * 配置lettuce連線池
     *
     * @return
     */
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.redis.cluster.lettuce.pool")
    public GenericObjectPoolConfig redisPool() {
        return new GenericObjectPoolConfig();
    }

    /**
     * 配置第一個資料來源的
     *
     * @return
     */
    @Bean("redisClusterConfig")
    @Primary
    public RedisClusterConfiguration redisClusterConfig() {

        Map<String,Object> source = new HashMap<>(8);
        source.put("spring.redis.cluster.nodes",environment.getProperty("spring.redis.cluster.nodes"));
        RedisClusterConfiguration redisClusterConfiguration;
        redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration",source));
        redisClusterConfiguration.setPassword(environment.getProperty("spring.redis.password"));
        return redisClusterConfiguration;

    }


    /**
     * 配置第一個資料來源的連線工廠
     * 這裡注意:需要新增@Primary 指定bean的名稱,目的是為了建立兩個不同名稱的LettuceConnectionFactory
     *
     * @param redisPool
     * @param redisClusterConfig
     * @return
     */
    @Bean("lettuceConnectionFactory")
    @Primary
    public LettuceConnectionFactory lettuceConnectionFactory(GenericObjectPoolConfig redisPool,@Qualifier("redisClusterConfig") RedisClusterConfiguration redisClusterConfig) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(redisPool).build();
        return new LettuceConnectionFactory(redisClusterConfig,clientConfiguration);
    }


    /**
     * 配置第一個資料來源的RedisTemplate
     * 注意:這裡指定使用名稱=factory 的 RedisConnectionFactory
     * 並且標識第一個資料來源是預設資料來源 @Primary
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean("redisTemplate")
    @Primary
    public RedisTemplate redisTemplate(@Qualifier("lettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
        return getRedisTemplate(redisConnectionFactory);

    }




    /**
     * 配置第二個資料來源
     *
     * @return
     */
    @Bean("secondaryRedisClusterConfig")
    public RedisClusterConfiguration secondaryRedisConfig() {

        Map<String,environment.getProperty("spring.secondaryRedis.cluster.nodes"));
        RedisClusterConfiguration redisClusterConfiguration;
        redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration",source));
        redisClusterConfiguration.setPassword(environment.getProperty("spring.redis.password"));

        return redisClusterConfiguration;
    }

    @Bean("secondaryLettuceConnectionFactory")
    public LettuceConnectionFactory secondaryLettuceConnectionFactory(GenericObjectPoolConfig redisPool,@Qualifier("secondaryRedisClusterConfig")RedisClusterConfiguration secondaryRedisClusterConfig) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(redisPool).build();
        return new LettuceConnectionFactory(secondaryRedisClusterConfig,clientConfiguration);
    }

    /**
     * 配置第一個資料來源的RedisTemplate
     * 注意:這裡指定使用名稱=factory2 的 RedisConnectionFactory
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean("secondaryRedisTemplate")
    public RedisTemplate secondaryRedisTemplate(@Qualifier("secondaryLettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
        return getRedisTemplate(redisConnectionFactory);
    }



    private RedisTemplate getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String,JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key採用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也採用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式採用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式採用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

}

複製程式碼