首页 > 解决方案 > 无法使用 Spring boot 创建多个 Redis Sentinel Lettuce 连接

问题描述

所以目前的要求是这样的。

  1. 两个独立的 Redis Sentinel 服务器
  2. 一个用作数据库,一个用作缓存

问题仅在于哨兵

我能够为数据库和缓存创建配置。但是官方的 RedisSentinelConfiguration 类有以下硬编码的字段。 因此缓存连接也指向数据库连接。

在此处输入图像描述

以下是我的 redis 配置文件

@Configuration
public class RedisConfig {

    @Value("${redis.type}")
    String redisType;

    @Value("${redis.commandTimeOut}")
    Duration commandTimeOut;

    @Bean(name = "jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        byte[] decodedBytes = Base64.getUrlDecoder().decode("aGVsbG8=");

        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setPassword(new String(decodedBytes));
        encryptor.setPoolSize(1);
        encryptor.setProvider(new BouncyCastleProvider());
        encryptor.setAlgorithm("PBEWITHSHA256AND256BITAES-CBC-BC");
        encryptor.setKeyObtentionIterations(1000);
        encryptor.setSaltGenerator(new org.jasypt.salt.RandomSaltGenerator());
        return encryptor;
    }

    protected LettuceConnectionFactory clusterConnectionFactory(final RedisProperties redisProperties) {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        final LettuceClientConfiguration.LettuceClientConfigurationBuilder lettuceClientConfigurationBuilder = LettuceClientConfiguration
                .builder().commandTimeout(redisProperties.getTimeout());
        if (redisProperties.isSsl()) {
            lettuceClientConfigurationBuilder.useSsl();
        }
        final LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build();
        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }

    protected LettuceConnectionFactory standaloneConnectionFactory(final RedisProperties redisProperties) {

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();

        if (!DigitalApiUtils.isBlankStr(redisProperties.getPassword())) {
            redisStandaloneConfiguration.setPassword(redisProperties.getPassword());
        }
        redisProperties.setPort(redisProperties.getPort());
        redisStandaloneConfiguration.setHostName(redisProperties.getHost());
        final LettuceClientConfiguration.LettuceClientConfigurationBuilder lettuceClientConfigurationBuilder = LettuceClientConfiguration
                .builder().commandTimeout(redisProperties.getTimeout());
        if (redisProperties.isSsl()) {
            lettuceClientConfigurationBuilder.useSsl();
        }
        final LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build();
        return new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
    }

    protected LettuceConnectionFactory sentinelConnectionFactory(final RedisProperties redisProperties) {

        RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
                .master(redisProperties.getSentinel().getMaster());
        redisProperties.getSentinel().getNodes().forEach(s -> sentinelConfig.sentinel(s, redisProperties.getPort()));
        sentinelConfig.setPassword(redisProperties.getPassword());
        sentinelConfig.setSentinelPassword(redisProperties.getPassword());
        return new LettuceConnectionFactory(sentinelConfig, LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build());
    }

    @Bean
    @Qualifier("redisConnectionFactory")
    @Primary
    protected LettuceConnectionFactory redisConnectionFactory(final RedisProperties redisProperties) {
        LettuceConnectionFactory connectionFactory = null;
        switch (redisType) {
            case "STANDALONE":
                connectionFactory = standaloneConnectionFactory(redisProperties);
                break;

            case "SENTINEL":
                connectionFactory = sentinelConnectionFactory(redisProperties);
                break;

            case "CLUSTER":
                connectionFactory = clusterConnectionFactory(redisProperties);
                break;
            default:
                connectionFactory = standaloneConnectionFactory(redisProperties);
                break;
        }
        return connectionFactory;
    }


    @Bean
    @Qualifier("stringRedisTemplate")
    @Primary
    StringRedisTemplate stringRedisTemplate(final RedisProperties redisProperties) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory(redisProperties));
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.setValueSerializer(new StringRedisSerializer());
        return stringRedisTemplate;
    }

}
@Configuration
public class RedisCacheConfig {

    @Value("${redis.cache.type}")
    String redisCacheType;

    @Value("${redis.commandTimeOut}")
    Duration commandTimeOut;

    protected LettuceConnectionFactory clusterConnectionFactory(final RedisCacheProperties redisProperties) {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        final LettuceClientConfiguration.LettuceClientConfigurationBuilder lettuceClientConfigurationBuilder = LettuceClientConfiguration
                .builder().commandTimeout(redisProperties.getTimeout());
        if (redisProperties.isSsl()) {
            lettuceClientConfigurationBuilder.useSsl();
        }
        final LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build();
        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }

    protected LettuceConnectionFactory standaloneConnectionFactory(final RedisCacheProperties redisProperties) {

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();

        if(!DigitalApiUtils.isBlankStr(redisProperties.getPassword())){
            redisStandaloneConfiguration.setHostName(redisProperties.getHost());
        }
        redisStandaloneConfiguration.setPassword(redisProperties.getPassword());
        redisProperties.setPort(redisProperties.getPort());
        final LettuceClientConfiguration.LettuceClientConfigurationBuilder lettuceClientConfigurationBuilder = LettuceClientConfiguration
                .builder().commandTimeout(redisProperties.getTimeout());
        if (redisProperties.isSsl()) {
            lettuceClientConfigurationBuilder.useSsl();
        }
        final LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build();
        return new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
    }

    protected LettuceConnectionFactory sentinelConnectionFactory(final RedisCacheProperties redisProperties) {

        RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
                .master(redisProperties.getSentinel().getMaster());
        redisProperties.getSentinel().getNodes().forEach(s -> sentinelConfig.sentinel(s, redisProperties.getPort()));
        sentinelConfig.setPassword(redisProperties.getPassword());
        sentinelConfig.setSentinelPassword(redisProperties.getPassword());
        return new LettuceConnectionFactory(sentinelConfig, LettuceClientConfiguration.builder().commandTimeout(commandTimeOut).build());
    }

    @Bean
    @Qualifier("redisCacheConnectionFactory")
    protected LettuceConnectionFactory redisCacheConnectionFactory(final RedisCacheProperties redisProperties) {
        LettuceConnectionFactory connectionFactory = null;
        switch (redisCacheType) {
            case "STANDALONE":
                connectionFactory = standaloneConnectionFactory(redisProperties);
                break;

            case "SENTINEL":
                connectionFactory = sentinelConnectionFactory(redisProperties);
                break;

            case "CLUSTER":
                connectionFactory = clusterConnectionFactory(redisProperties);
                break;
            default:
                connectionFactory = standaloneConnectionFactory(redisProperties);
                break;
        }
        return connectionFactory;
    }

    @Bean
    @Qualifier("redisCacheStringTemplate")
    StringRedisTemplate redisCacheStringTemplate(final RedisCacheProperties redisProperties) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisCacheConnectionFactory(redisProperties));
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.setValueSerializer(new StringRedisSerializer());
        return stringRedisTemplate;
    }

    @Bean
    @Qualifier("cacheHashOperations")
    public HashOperations cacheHashOperations(final RedisCacheProperties redisProperties) {
        return redisCacheStringTemplate(redisProperties).opsForHash();
    }
}

应用程序属性是

redis.type=SENTINEL


spring.redis.port=26379
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes={IP1}
spring.redis.password=password
spring.redis.timeout=PT20.345S
redis.commandTimeOut=3000ms

spring.cache.port=26379
spring.cache.sentinel.master=mymastercache
spring.cache.sentinel.nodes={IP2}
spring.cache.password=password
spring.cache.timeout=PT20.345S
redis.cache=3000ms

标签: javaspringspring-bootredislettuce

解决方案


推荐阅读