如何解决redis高并发客户端频繁time out

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决redis高并发客户端频繁time out相关的知识,希望对你有一定的参考价值。

参考技术A redis为什么会有高并发问题
redis的出身决定

Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用jedis等客户端对redis进行并发访问时会出现问题。发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。

同时,单线程的天性决定,高并发对同一个键的操作会排队处理,如果并发量很大,可能造成后来的请求超时。
在远程访问redis的时候,因为网络等原因造成高并发访问延迟返回的问题。
解决办法
在客户端将连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
服务器角度,利用setnx变向实现锁机制。

故障演练 Redis Cluster集群,当master宕机,主从切换,客户端报错 timed out

大家好,我是Tom哥

性能不够,缓存来凑

一个高并发系统肯定少不了缓存的身影,为了保证缓存服务的高可用,我们通常采用 Redis Cluster 集群模式。

描述:

集群部署采用了 3主3从 拓扑结构,数据读写访问master节点, slave节点负责备份。

随便登录一台 redis 节点,都可以看到集群的slot的槽位分步区间,以及对应的主从节点映射关系。

Redis Cluster 的最新集群信息

原因分析:

SpringBoot 2.X 版本, Redis默认的连接池采用 Lettuce

当Redis 集群节点发生变化后,Letture默认是不会刷新节点拓扑

解决方案:

Letture 二方包仲裁掉

相关二方包

master 节点宕机,看看系统的日志

初始化了 24 个连接。

然后,回归业务功能,读写缓存 数据也都是操作最新的主节点。

还有一种方案:刷新节点拓扑视图

Lettuce 官方描述:

https://github.com/lettuce-io/lettuce-core/wiki/Redis-Cluster#user-content-refreshing-the-cluster-topology-view

移动、重定向 的自适应更新

编写代码

@Bean(destroyMethod = "destroy")
public LettuceConnectionFactory lettuceConnectionFactory() 

    //开启 自适应集群拓扑刷新和周期拓扑刷新
    ClusterTopologyRefreshOptions clusterTopologyRefreshOptions =  ClusterTopologyRefreshOptions.builder()
            // 开启自适应刷新。否则,Redis集群变更后将会导致连接异常
            .enableAllAdaptiveRefreshTriggers() 
            // 自适应刷新超时时间(默认30秒)
            .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30)) 
            // 开周期刷新
            .enablePeriodicRefresh(Duration.ofSeconds(20))  
            .build();

    ClientOptions clientOptions = ClusterClientOptions.builder()
            .topologyRefreshOptions(clusterTopologyRefreshOptions)
            .build();

    LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
            .poolConfig(genericObjectPoolConfig(redisProperties.getJedis().getPool()))
            .clientOptions(clientOptions)
            .commandTimeout(redisProperties.getTimeout()) //默认RedisURI.DEFAULT_TIMEOUT 60
            .build();

    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 clusterConfiguration = new RedisClusterConfiguration();
    clusterConfiguration.setClusterNodes(nodes);
    clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
    clusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());

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



关于我:Tom哥,前阿里P7技术专家,offer收割机,参加多次淘宝双11大促活动。欢迎关注,我会持续输出更多经典原创文章,为你晋级大厂助力


目前微信群已开放,想进交流群的小伙伴请添加Tom哥微信,暗号「进群」,唠嗑聊天, 技术交流,围观朋友圈,人生打怪不再寂寞


推荐阅读

以上是关于如何解决redis高并发客户端频繁time out的主要内容,如果未能解决你的问题,请参考以下文章

故障演练 Redis Cluster集群,当master宕机,主从切换,客户端报错 timed out

redis其他问题

Redis系列教程:Redis并发竞争key的解决方案详解

Redis系列教程:Redis并发竞争key的解决方案详解

redis压测两小时后超时

海量数据和高并发的解决方案