【分享之路001】springboot整合双redis配置

本文介绍了如何在SpringBoot项目中实现双Redis配置,详细讲述了配置文件和代码的修改步骤,包括设置两个不同的RedisConnectionFactory和RedisTemplate,以实现数据的双写。注意在使用第二个RedisTemplate时,需通过@Resource注解并指定Bean名称,以避免冲突。
摘要由CSDN通过智能技术生成

springboot双redis配置

1. 背景

springboot项目中本来用到了redis,由于业务要求,需要将数据也写到另一个redis中

2. 配置文件改动

2.1 之前redis配置*

spring.redis.database=xx
spring.redis.host=xxxx
spring.redis.port=xxx
spring.redis.password=xxx

2.2 改动后的redis配置

#原有redis配置
spring.redis.database=XX
spring.redis.host=XXX
spring.redis.port=XXX
spring.redis.password=XXXX
#双写redis配置-单点
#spring.redis2.database=XXX
#spring.redis2.host=XXXX
#spring.redis2.port=XXXX
#spring.redis2.password=XXXXX

3.代码改动

3.1 之前代码

RedisCacheConfig.java

@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {

    private static final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class);

    private static final String HOST = "spring.redis.host";
    private static final String PORT = "spring.redis.port";
    private static final String DB_INDEX = "spring.redis.database";
    private static final String PASSWORD = "spring.redis.password";

    private static final String SENTINEL_NODES = "spring.redis.sentinel.nodes";
    private static final String SENTINEL_MASTER = "spring.redis.sentinel.master";

    @Value("${spring.redis.lettuce.pool.max-active}")
    private int pollMaxActive;

    @Value("${spring.redis.lettuce.pool.max-idle}")
    private int pollMaxIdle;

    @Value("${spring.redis.lettuce.pool.max-wait}")
    private int pollMaxWait;

    @Value("${spring.redis.lettuce.pool.min-idle}")
    private int pollMinIdle;

    @Value("${spring.redis.timeout}")
    private int timeout;

    /**
     * key产生器,可以不用
     *
     * @return
     */
    @Bean
    public KeyGenerator wiselyKeyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };

    }

    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig() {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(pollMaxIdle);
        poolConfig.setMaxTotal(pollMaxActive);
        poolConfig.setMaxWaitMillis(pollMaxWait);
        poolConfig.setMinIdle(pollMinIdle);
        return poolConfig;
    }

    @Bean
    public LettuceClientConfiguration lettuceClientConfiguration(GenericObjectPoolConfig genericObjectPoolConfig) {
        return LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(timeout))
                .poolConfig(genericObjectPoolConfig)
                .build();
    }

    @Bean
    public RedisConnectionFactory redisOneConnectionFactory() {
        int dbIndex = ConfigUtil.getInt(DB_INDEX, -1);
        String host = ConfigUtil.getValue(HOST);
        int port = ConfigUtil.getInt(PORT, -1);
        String password = ConfigUtil.getValue(PASSWORD);
        String sentinelNodes = ConfigUtil.getValue(SENTINEL_NODES);
        String sentinelMaster = ConfigUtil.getValue(SENTINEL_MASTER);
        return createLettuceConnectionFactory(dbIndex, host, port, password, sentinelNodes, sentinelMaster);
    }

    public LettuceConnectionFactory createLettuceConnectionFactory(int dbIndex, String host, int port, String password, String sentinelNodes, String sentinelMaster) {
        if (!StringUtils.isEmpty(sentinelNodes)) {
            RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(sentinelMaster, getSentinelNodes(sentinelNodes));
            redisSentinelConfiguration.setDatabase(dbIndex);
            redisSentinelConfiguration.setPassword(password);
            return new LettuceConnectionFactory(redisSentinelConfiguration, lettuceClientConfiguration(genericObjectPoolConfig()));
        } else if (!StringUtils.isEmpty(host)) {
            RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
            redisStandaloneConfiguration.setDatabase(dbIndex);
            redisStandaloneConfiguration.setHostName(host);
            redisStandaloneConfiguration.setPort(port);
            redisStandaloneConfiguration.setPassword(password);
            return new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration(genericObjectPoolConfig()));
        } else {
            logger.error("未配置redis单点或哨兵,请检查配置文件!");
            return null;
        }
    }

    private Set<String> getSentinelNodes(String sentinelNodes) {
        String[] nodes = sentinelNodes.split(",");
        return new HashSet<>(Arrays.asList(nodes));
    }

    /**
     * 序列化
     *
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, String> redisTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisOneConnectionFactory());
        setSerializer(template);
        template.afterPropertiesSet();
        template.setEnableTransactionSupport(true);
        return template;
    }

    private void setSerializer(StringRedisTemplate template) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }

}

3.2 改动之后的代码

RedisTwoCacheConfig.java

@Configuration
public class RedisTwoCacheConfig extends CachingConfigurerSupport {

    private static final Logger logger = LoggerFactory.getLogger(RedisTwoCacheConfig.class);

    private static final String HOST = "spring.redis2.host";
    private static final String PORT = "spring.redis2.port";
    private static final String DB_INDEX = "spring.redis2.database";
    private static final String PASSWORD = "spring.redis2.password";

    private static final String SENTINEL_NODES = "spring.redis2.sentinel.nodes";
    private static final String SENTINEL_MASTER = "spring.redis2.sentinel.master";

    // 复用redis1的连接池配置
    @Value("${spring.redis.lettuce.pool.max-active}")
    private int pollMaxActive;

    @Value("${spring.redis.lettuce.pool.max-idle}")
    private int pollMaxIdle;

    @Value("${spring.redis.lettuce.pool.max-wait}")
    private int pollMaxWait;

    @Value("${spring.redis.lettuce.pool.min-idle}")
    private int pollMinIdle;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig() {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(pollMaxIdle);
        poolConfig.setMaxTotal(pollMaxActive);
        poolConfig.setMaxWaitMillis(pollMaxWait);
        poolConfig.setMinIdle(pollMinIdle);
        return poolConfig;
    }

    @Bean
    public LettuceClientConfiguration lettuceClientConfiguration(GenericObjectPoolConfig genericObjectPoolConfig) {
        return LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofMillis(timeout))
                .poolConfig(genericObjectPoolConfig)
                .build();
    }

    /**
     * 配置redis连接工厂
     *
     * @return
     */
    @Primary
    @Bean
    public RedisConnectionFactory redisTwoConnectionFactory() {
        int dbIndex = ConfigUtil.getInt(DB_INDEX, -1);
        String host = ConfigUtil.getValue(HOST);
        int port = ConfigUtil.getInt(PORT, -1);
        String password = ConfigUtil.getValue(PASSWORD);
        String sentinelNodes = ConfigUtil.getValue(SENTINEL_NODES);
        String sentinelMaster = ConfigUtil.getValue(SENTINEL_MASTER);
        return createLettuceConnectionFactory(dbIndex, host, port, password, sentinelNodes, sentinelMaster);
    }

    public LettuceConnectionFactory createLettuceConnectionFactory(int dbIndex, String host, int port, String password, String sentinelNodes, String sentinelMaster) {
        if (!StringUtils.isEmpty(sentinelNodes)) {
            RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(sentinelMaster, getSentinelNodes(sentinelNodes));
            redisSentinelConfiguration.setDatabase(dbIndex);
            redisSentinelConfiguration.setPassword(password);
            return new LettuceConnectionFactory(redisSentinelConfiguration, lettuceClientConfiguration(genericObjectPoolConfig()));
        } else if (!StringUtils.isEmpty(host)) {
            RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
            redisStandaloneConfiguration.setDatabase(dbIndex);
            redisStandaloneConfiguration.setHostName(host);
            redisStandaloneConfiguration.setPort(port);
            redisStandaloneConfiguration.setPassword(password);
            return new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration(genericObjectPoolConfig()));
        } else {
            logger.error("未配置redis单点或哨兵,请检查配置文件!");
            return null;
        }
    }

    private Set<String> getSentinelNodes(String sentinelNodes) {
        String[] nodes = sentinelNodes.split(",");
        return new HashSet<>(Arrays.asList(nodes));
    }

    /**
     * 配置redisTemplate 注入方式使用@Resource(name="") 方式注入
     *
     * @return
     */
    @Bean(name = "redisTwoTemplate")
    public RedisTemplate<String, String> redisTwoTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisTwoConnectionFactory());
        setSerializer(template);
        template.afterPropertiesSet();
        template.setEnableTransactionSupport(true);
        return template;
    }

    /**
     * key产生器,可以不用
     *
     * @return
     */
    @Bean
    public KeyGenerator wiselyKeyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };

    }

    private void setSerializer(StringRedisTemplate template) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }

}

3.3 service层代码

@Component
public class XXXServiceImpl implements XXXService {
    private final static Logger logger = LoggerFactory.getLogger(XXXServiceImpl.class);
    
    @Autowired
    RedisTemplate redisTemplate;

    @Resource(name = "redisTwoTemplate")
    RedisTemplate redisTwoTemplate;
	
	/**
	* 此处为模拟真实的方法调用
	**/
	public handler() {
		String key = "redis"
		Object valueOne = redisTemplate.get(key);
		Object valueTwo = redisTwoTemplate.get(key);
	}
   }

4 注意点

  • 第二个redisTemplate必须用Resource指明Bean名称,否则报错
  • 第二个redis配置项,原则上对名称不做要求,但为了好理解,所以命名为redis2,其他保持不变

作者寄语:说实话,好久没写文章了,后面会经常写写,将工作中用到的小技巧或好的方式方法分享给大家,不喜勿喷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值