首页 > 数据库 >关于spring.redis.cluster集群部分Master节点故障后 交易中断60秒解决方案

关于spring.redis.cluster集群部分Master节点故障后 交易中断60秒解决方案

时间:2024-01-22 18:07:47浏览次数:20  
标签:spring redis springframework 60 服务器 redisProperties org import


 背景

   第一种方案:

公司项目做性能测试,redis集群选用cluster集群模式,开始选用3主3从,共3台服务器,每个服务器一主一从。

       服务器A   redis 8001  8002

       服务器B   redis 8003  8004 

       服务器C   redis 8005  8006 

     8001 主  

     8002 从 (主为8003)

     8003 主

     8004 从(主为8005)

     8005 主

     8006从(主为8001)

            

 1.停止服务器A      

     此时集群状态为

      8003 主

     8004 从(主为8005)

     8005 主

     8006 主(代替8001)

2.启动服务器A

  此时集群状态为

     8001 从 (主为8006)

     8002 从 (主为8003)

     8003 主

     8004 从(主为8005)

     8005 主

     8006 主 

3.停止服务器C

   由于C服务器现承载两个主节点,服务器停止 导致集群过半数主节点停止,集群瘫痪

总结 :此方案在业内较为流行,但不是最完美的解决方案,若遇到此种情况 无法避免

第二种方案:

   服务器A   redis 8001 

   服务器B   redis 8002   

   服务器C   redis 8003   

   服务器D   redis 8004

   服务器E   redis 8005

   服务器F   redis 8006

随意启停服务均可实现高可用,但是此时又暴露出一个问题  

重头戏

停止Master节点及Slave节点过程中,出现停止部分Master节点交易中断60秒无法连接情况,该问题主要原因为Redis集群本身高可用切换结束之后,应用程序没有及时更新集群拓扑信息(spring-boot-starter-data-jpa框架默认关闭了集群拓扑刷新机制,默认刷新时间为60秒),从而导致交易中断 60秒的情况 

步骤一:将RedisConfiguration.java添加到应用的cofing文件夹中(

import io.lettuce.core.ReadFrom;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Redis配置
 *
 * @author zhaoxg
 */
@Slf4j
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {
    @Autowired
    private RedisProperties redisProperties;

    @Bean(destroyMethod = "destroy")
    public LettuceConnectionFactory redisConnectionFactory() {
        // redis单节点
        if (null == redisProperties.getCluster() || null == redisProperties.getCluster().getNodes()) {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(),
                    redisProperties.getPort());
            configuration.setPassword(redisProperties.getPassword());
            return new LettuceConnectionFactory(configuration);
        }

        // redis集群
        List<String> clusterNodes = redisProperties.getCluster().getNodes();
        Set<RedisNode> nodes = new HashSet<RedisNode>();
        clusterNodes.forEach(address -> nodes.add(new RedisNode(address.split(":")[0].trim(), Integer.valueOf(address.split(":")[1]))));
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        redisClusterConfiguration.setClusterNodes(nodes);
        //RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        redisClusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());

        GenericObjectPoolConfig<?> genericObjectPoolConfig = new GenericObjectPoolConfig<>();
        genericObjectPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
        genericObjectPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        genericObjectPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
        genericObjectPoolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().getSeconds());
        
       
        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                .enableAllAdaptiveRefreshTriggers()
                .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(3))
                .enablePeriodicRefresh(Duration.ofSeconds(6))
                .build();

        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions).build();

        LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(genericObjectPoolConfig)
                .clientOptions(clusterClientOptions)
                .commandTimeout(redisProperties.getTimeout()).build();

        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
        lettuceConnectionFactory.setShareNativeConnection(false);// 是否允许多个线程操作共用同一个缓存连接,默认 true,false 时每个操作都将开辟新的连接
        lettuceConnectionFactory.resetConnection();// 重置底层共享连接, 在接下来的访问时初始化
        return lettuceConnectionFactory;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

关于spring.redis.cluster集群部分Master节点故障后 交易中断60秒解决方案_spring

步骤二:修改应用pom.xml文件,添加comm-pools依赖;

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>

关于spring.redis.cluster集群部分Master节点故障后 交易中断60秒解决方案_redis_02

步骤三:修改application文件

spring.redis.timeout=3000
spring.redis.cluster.max-redirects=5
spring.redis.cluster.nodes=集群信息
spring.redis.lettuce.pool.max-active=1000
spring.redis.lettuce.pool.max-idle=100
spring.redis.lettuce.pool.max-wait=5000
spring.redis.lettuce.pool.min-idle=5
spring.redis.password=密码

关于spring.redis.cluster集群部分Master节点故障后 交易中断60秒解决方案_服务器_03



标签:spring,redis,springframework,60,服务器,redisProperties,org,import
From: https://blog.51cto.com/u_16527461/9368349

相关文章

  • 能用到退休的600条Linux命令,助你解决95%的问题
    你们好,我的网工朋友。曾经传统网工的工作中,很少用到Linux,但网络技术的更新,搞网络,多少得会点这玩意儿。正所谓书到用时方恨少,命令到用时全忘了,Linux命令真心多到爆炸。这不,今天就给你来一篇史上最全Linux命令总结的文章,命令有点多,一不小心整理了2w字,建议先收藏后阅读哈。今日文章阅......
  • 语音合成技术(深度学习方法简介)https://www.cnblogs.com/jacen789/p/14260194.html
    语音合成技术(深度学习方法简介)一、定义语音合成(Text-To-Speech,简称TTS),又称文语转换技术,是将文字信息转变为可以听得懂的、流利的语音输出的一种技术。其与我们比较熟悉的语音识别技术(AutomaticSpeechRecognition,简称ASR)目标相反。ASR是将声音转化为文字,类比于人类的耳朵;而TT......
  • springboot 读取配置7种方式
    1.概述通过了解springboot加载配置,可以更方便地封装自定义Starter。在SpringBoot中,可以使用以下6种方式读取yml、properties配置:使用@Value注解:读取springboot全局配置文件单个配置。使用Environment接口:通过Environment接口动态获取配置。(将yml全部数据封装到Environ......
  • Idea 创建SpringBoot小计
    创建spring工程之后maven依赖包拉不下来去官网下载maven并配置maven环境变量  下载地址:http://maven.apache.org/download.cgi解压后,修改mavensetting配置文件,增加国内镜像地址添加阿里云国内镜像  idea配置本地maven配置如下图  之后应该就......
  • 记录一次 SpringBoot 自动装配失败
    项目业务模块引入公共模块,公共模块的bean死活自动装配失败,如下图:想要自动装配bean的类型是PasswordEncoder,但是就是装配不上去仔细检查后发现本应该是2层目录的META-INF/spring成了1层名叫META-INFO.spring的目录原来resource层级下新建目录在后面加.下一层目录不像在ja......
  • Spring中的容器和Bean
    目录1.Spring整体设计架构1.1BeanRegistry系列接口及BeanFactory接口关系1.1.1BeanFactory接口1.1.2BeanRegistry系列接口1.1.2.1BeanDefinitionRegistry接口及DefaultListableBeanFactory实现类1.1.2.2SingletonBeanRegistry接口及DefaultSingletonBeanRegistry实现类1.2......
  • Redis分布式锁
    Redis分布式锁今天在做Lottery分布式抽奖项目中,接触到了分布式锁这个概念,普通单机系统中,我们可以使用mutex、cas等方式来确保不同线程之间的同步和互斥,但是显然在分布式系统下,如果想让所有机器在同一时刻只有一个线程可以访问到某个共享资源,那么传统的互斥方法不再可用。这时候就......
  • CodeForces 1609G A Stroll Around the Matrix
    洛谷传送门CF传送门我独立做出一道*3000?考虑对于单次询问,除了\(O(nm)\)的dp,有没有什么方法能快速算出答案。发现若\(a_{i+1}-a_i<b_{j+1}-b_j\)则\(i\getsi+1\),否则\(j\getsj+1\)是最优的。这个贪心的证明不难,考虑当前新走到某一行或某一列的贡献......
  • 记录使用Redis当分布式锁
    在网上看到一次使用redis当分布式锁的文章,我就自己写了个demo前置条件:建议新建一个springboot工程(添加web依赖),然后自行整合mybatisplus、redis,可以参照以下链接:mybatisPlus:https://blog.csdn.net/wang20000102/article/details/132615071redis:https://blog.csdn.net/lwj_07/art......
  • springboot升级到2.6.x和2.7.x 兼容hystrix
    一、pom.xml需要引入的依赖二、项目开启熔断器开关2.1注解方式2.2xml方式三、依赖类缺失问题四、版本匹配安全检查问题五、测试验证六、结论一、pom.xml需要引入的依赖1<!--springboot升级到2.6.7,同样适用于2.7.0,2.7.18等-->2<parent>3......