springboot配置多個redis數據源,並訂閱redis管道

配置多個數據源,數據源爲redis集羣

spring:
  application:
    name: XXX
  redis:
    cluster:
      nodes: Ip:Port,Ip:Port,Ip:Port
    password:
    test-on-borrow: true
    timeout: 10000 #按照各自業務需求配置超時時間
    lettuce:
      pool:
        max-active: 200
        max-idle: 200
        max-wait: 5000
        min-idle: 10
  secondaryRedis:
    cluster:
      nodes: Ip:Port,Ip:Port,Ip:Port
    password:
/**
 * Redis配置聲明
 * 
 */
@Configuration
public class RedisConfig {
    //如果單個數據源,直接使用lettuceConnectionFactory,不要單獨配置
    //@Autowired
    //public LettuceConnectionFactory lettuceConnectionFactory;

    //監聽執行方法
    @Autowired
    IndexListener indexListener;

    //監聽執行方法
    @Autowired
    SendIndexPriceListener sendIndexPriceListener;

    //聲明temp
    @Resource(name = "secondaryRedisTemplate")
    private RedisTemplate secondaryRedisTemplate;

    //聲明temp
    @Resource(name = "stringRedisTemplate")
    private RedisTemplate stringRedisTemplate;



    /**
     * 監聽
     * @return
     */
    @Bean
    RedisMessageListenerContainer indexMessageListenerContainer(){
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(stringRedisTemplate.getConnectionFactory());
        redisMessageListenerContainer.setTaskExecutor(threadPool());
        redisMessageListenerContainer.addMessageListener(indexListener, new ChannelTopic("管道名稱"));
        redisMessageListenerContainer.afterPropertiesSet();
        return redisMessageListenerContainer;
    }

    /**
     * 監聽 指數推送
     * @return
     */
    @Bean
    RedisMessageListenerContainer sendIndexPriceListenerContainer(){

        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(secondaryRedisTemplate.getConnectionFactory());
        redisMessageListenerContainer.setTaskExecutor(threadPool());
        //監聽器,管道名稱
        redisMessageListenerContainer.addMessageListener(sendIndexPriceListener,
                new ChannelTopic("管道名稱"));
        redisMessageListenerContainer.afterPropertiesSet();
        return redisMessageListenerContainer;
    }

    public ExecutorService threadPool(){
        return Executors.newFixedThreadPool(30);
    }
}

配置多個數據源

@Configuration
public class GenerateNewTemplateRedisConfig {

    @Autowired
    private Environment environment;
    /**
     * 配置lettuce連接池
     *
     * @return
     */
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.redis.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(RedisPassword.of(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);
    }

    /**
     * 配置第一個數據源的stringRedisTemplate
     * 注意:這裏指定使用名稱=factory 的 RedisConnectionFactory
     * 並且標識第一個數據源是默認數據源 @Primary
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean("stringRedisTemplate")
    @Primary
    public StringRedisTemplate stringRedisTemplate(@Qualifier("lettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
        return getRedisTemplate(redisConnectionFactory);
    }

    /**
     * 配置第二個數據源
     *
     * @return
     */
    @Bean("secondaryRedisClusterConfig")
    public RedisClusterConfiguration secondaryRedisConfig() {
        Map<String, Object> source = new HashMap<>(8);
        source.put("spring.redis.cluster.nodes", environment.getProperty("spring.secondaryRedis.cluster.nodes"));
        RedisClusterConfiguration redisClusterConfiguration;
        redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));
        redisClusterConfiguration.setPassword(RedisPassword.of(environment.getProperty("spring.secondaryRedis.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 StringRedisTemplate secondaryRedisTemplate(@Qualifier("secondaryLettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
        return getRedisTemplate(redisConnectionFactory);
    }

    //返回Template並綁定RedisConnectionFactory
    private StringRedisTemplate getRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        return template;
    }

}
/**
 * 監聽執行方法
 * 
 */
@Slf4j
@Component
public class SendIndexPriceListener extends MessageListenerAdapter {

    @Autowired
    LocalCache localCache;

    @Autowired
    IndexPriceService indexPriceService;

    @Autowired
    private SingleContractStopCache singleContractStopCache;

    public SendIndexPriceListener() {
        super();
        super.afterPropertiesSet();
    }

    public void handleMessage(String message, String channel) {
        try {
            String currencyId = "";
            String contractIdStr = "";

            if (org.apache.commons.lang3.StringUtils.isEmpty(message)) {

                log.error("message error, message :: {} ", message);

            }

            SendIndexPriceDto sendIndexPriceDto = JSON.parseObject(message, SendIndexPriceDto.class);

            boolean isLostParam = (org.apache.commons.lang3.StringUtils.isEmpty(sendIndexPriceDto.getTradePair()));//判斷幣種名稱
            boolean isLostIndexPrice = StringUtils.isEmpty(sendIndexPriceDto.getIndexPrice());//判斷指數價格
            if (isLostParam || isLostIndexPrice) {
                log.error("isLostParam or isLostIndexPrice error, isLostParam or isLostIndexPrice :: {} ", "is null");
            }
            //獲取全部數據
            List<Contract> contractList = 查詢數據庫或Redis數據;

            //業務邏輯
            String[] tradePairArray = sendIndexPriceDto.getTradePair().toUpperCase().split("_");
            if (tradePairArray.length > 0) {
                Map<String, String> tradePairMap = contractList.stream().collect(Collectors.toMap(a -> a.getCurrencyName().toUpperCase(), a -> a.getCurrencyId() + "_" + a.getSeq()));
                if (tradePairMap.containsKey(tradePairArray[0].toUpperCase())) {
                    String[] currencySeq = tradePairMap.get(tradePairArray[0].toUpperCase()).split("_");
                    currencyId = currencySeq[0];
                    contractIdStr = currencySeq[1];
                }
            } else {
                log.error("currencyName error, currencyName :: {}", "is null");
            }

            Long id = Long.valueOf(currencyId);
            BigDecimal price = new BigDecimal(sendIndexPriceDto.getIndexPrice());
            if (price.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("price error, price :: {} < 0", price);
            }

            price = price.setScale(8, RoundingMode.DOWN);

            IndexPrice indexPriceBean = IndexPrice.builder()
                    .currencyId(id)
                    .price(price)
                    .createdDate(new Date())
                    .build();

            if (!CollectionUtils.isEmpty(contractList)) {
                Map<Long, Long> currencyContractMap = contractList.stream().collect(Collectors.toMap(a -> a.getCurrencyId(), a -> a.getSeq()));
                if (currencyContractMap.containsKey(id)) {
                    Long contractId = currencyContractMap.get(id);
                    if (singleContractStopCache.singleContractFlagStatus(contractId)) {
                        log.warn("contract is stop trade, indexPrice stop !!! contract ::: {}", currencyContractMap.get(id));
                    }
                    indexPriceBean.setContractId(currencyContractMap.get(id));
                }
            }
            indexPriceService.updIndexPrice(indexPriceBean);
            log.debug("update success,contract :: {}, index price :: {}, time :: {}", contractIdStr, sendIndexPriceDto.getIndexPrice(), sendIndexPriceDto.getCreateTime());
            } catch (Exception e) {
                log.error("deal channel :: 【{}】 message :: {} fail!", channel, message, e);
            }
        }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章