首页 > 数据库 >Redis集群Lettuce主从切换问题

Redis集群Lettuce主从切换问题

时间:2024-09-05 15:55:54浏览次数:12  
标签:lettuce redis 刷新 Redis springframework Lettuce import org 主从

一、问题描述

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

二、原因

SpringBoot2.X版本开始Redis默认的连接池都是采用的Lettuce。当节点发生改变后,Letture默认是不会刷新节点拓扑的。

三、解决方案

3.1 方案一:把lettuce换成jedis

只需要在pom.xml里调整一下依赖的引用

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-redis</artifactId>
           <version>2.1.5.RELEASE</version>
               <!-- 不用lettuce ,用jedis -->
               <exclusions>
                   <exclusion>
                       <groupId>io.lettuce</groupId>
                       <artifactId>lettuce-core</artifactId>
                   </exclusion>
               </exclusions>
       </dependency>


       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>3.1.0-m4</version>
       </dependency>
3.2 方案二:刷新节点拓扑视图

Redis节点异常,服务端的Redis集群拓扑被刷新了,Java程序没有获取到新的拓扑。

Lettuce官方文档中关于Redis Cluster的相关说明:Lettuce处理Moved和Ask永久重定向,由于命令重定向,你必须刷新节点拓扑视图。而自适应拓扑刷新(Adaptive updates)与定时拓扑刷新(Periodic updates)是默认关闭的,可以通过如下代码打开。

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

Redis集群Lettuce主从切换问题_redis

修改代码如下

package com.montnets.common.redis;

import io.lettuce.core.ClientOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
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.stereotype.Component;

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

@Component
public class RedisPoolConfig {

    @Autowired
    private RedisProperties redisProperties;

    public GenericObjectPoolConfig<?> genericObjectPoolConfig(RedisProperties.Pool properties) {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(properties.getMaxActive());
        config.setMaxIdle(properties.getMaxIdle());
        config.setMinIdle(properties.getMinIdle());
        if (properties.getTimeBetweenEvictionRuns() != null) {
            config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis());
        }
        if (properties.getMaxWait() != null) {
            config.setMaxWaitMillis(properties.getMaxWait().toMillis());
        }
        return config;
    }

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

        //开启 自适应集群拓扑刷新和周期拓扑刷新
        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions =  ClusterTopologyRefreshOptions.builder()
                // 开启全部自适应刷新
                .enableAllAdaptiveRefreshTriggers() // 开启自适应刷新,自适应刷新不开启,Redis集群变更时将会导致连接异常
                // 自适应刷新超时时间(默认30秒)
                .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30)) //默认关闭开启后时间为30秒
                // 开周期刷新
                .enablePeriodicRefresh(Duration.ofSeconds(20))  // 默认关闭开启后时间为60秒 ClusterTopologyRefreshOptions.DEFAULT_REFRESH_PERIOD 60  .enablePeriodicRefresh(Duration.ofSeconds(2)) = .enablePeriodicRefresh().refreshPeriod(Duration.ofSeconds(2))
                .build();

        // https://github.com/lettuce-io/lettuce-core/wiki/Client-Options
        ClientOptions clientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions)
                .build();

        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .poolConfig(genericObjectPoolConfig(redisProperties.getJedis().getPool()))
                //.readFrom(ReadFrom.MASTER_PREFERRED)
                .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);
        // lettuceConnectionFactory.setShareNativeConnection(false); //是否允许多个线程操作共用同一个缓存连接,默认true,false时每个操作都将开辟新的连接
        // lettuceConnectionFactory.resetConnection(); // 重置底层共享连接, 在接下来的访问时初始化
        return lettuceConnectionFactory;
    }
}

标签:lettuce,redis,刷新,Redis,springframework,Lettuce,import,org,主从
From: https://blog.51cto.com/u_13529088/11928620

相关文章

  • Redis集群不停机升级
    背景现有的Redis集群是由Redis4.x部署的,现在根据需要,要将Redis4.x升级到Redis5.0.10版本,且现有的Redis集群不能停机。下面以本地的机器为例进行操作演示。操作步骤下载&安装Redis5.0.10目前的Redis集群部署在/usr/local/redis目录下,/usr/local下执行命令下载Redis5.0.10cd......
  • Redis篇 - 深入了解查询缓存与缓存带来的问题
    引言在现代Web应用程序中,为了提高数据访问速度和减轻数据库的压力,缓存技术变得越来越重要。Redis作为一款高性能的键值存储系统,在缓存领域有着广泛的应用。然而,随着缓存的引入,一系列新的挑战也随之而来。本文将探讨查询缓存的基本概念以及常见的几个问题:读写不一致、缓存穿透......
  • windows系统Redis安装,启动与客户端连接,redis-python模块安装
    1、https://www.cnblogs.com/chunyouqudongwuyuan/p/16475220.html#redis%E5%9F%BA%E6%9C%AC%E8%BF%9E%E6%8E%A5Redis安装,启动与客户端连接,redis-python模块安装redis安装由于windows对redis支持不好,所以在windows下只能使用较老版本的redis只维护到3.x https://github.c......
  • Docker 部署 Redis (图文并茂超详细)
    部署Redis(Docker)[Step1]:拉取Redis镜像,推荐使用7的Redis版本dockerpullredis:7.0.12[Step2]:创建Redis相关目录➡️启动Redis容器➡️拷贝文件➡️授权文件夹➡️删除容器#创建Redis相关目录mkdir-p/data/redis/{conf,data,log}t......
  • 推荐一款开源、高效、灵活的Redis桌面管理工具:Tiny RDM!支持调试与分析功能!
    1、引言在大数据和云计算快速发展的今天,Redis作为一款高性能的内存键值存储系统,在数据缓存、实时计算、消息队列等领域发挥着重要作用。然而,随着Redis集群规模的扩大和复杂度的增加,如何高效地管理和运维Redis数据库成为了许多开发者和运维人员面临的挑战。TinyRDM(TinyRedisDes......
  • redis内存碎片
    一、什么是内存碎片redis数据删除后,所占用内存不会马上换给操作系统,而是交给内存分配管理器,所以对操作系统来说redis仍然占用着这些内存。这里有个风险点是:redis释放的内存有可能是不联系的,这种不连续的内存很可能无法再次使用,最终造成了内存的浪费。二、如何判断有内存碎片可......
  • redis-cli创建Redis集群时显式指定主从节点
    背景前些年用python写过一个RedisCluster自动化安装,扩容和缩容的工具,虽然当时官方的的redis-trib.rb集群创建工具提供了集群创建、检查、修复、均衡等命令行功能,个人接受不了redis-trib.rb,原因在于redis-trib.rb需要ruby的环境,同时无法自定义指定集群中节点的主从关系。随后R......
  • 如何构建高并发抢购系统(PHP+Redis)
    为了构建一个高并发抢购系统,并确保系统设计具有良好的可扩展性和维护性,可以结合设计模式进行详细设计。以下是结合设计模式的抢购系统详细设计:1.系统概述抢购系统的目标是处理大量用户的并发抢购请求,确保每个用户能够公平地参与抢购,并且避免超卖。设计一个高效的系统涉及以......
  • 从初识Redis到精通Redis,一份Java程序员必备Redis实战文档分享
    本文深入浅出的介绍了Redis的五种数据类型,并通过多个实用示例展示了Redis的用法。除此之外还讲述了Redis的优化方法和扩展方法。一共由三个部分组成,第一部分对Redis进行了介绍,说明了Redis的基本使用方法、它拥有的5种数据结构以及操作5种数据结构的命令,并详解了如何使用R......
  • 【Azure Redis】Redis-CLI连接Redis 6380端口始终遇见 I/O Error
    问题描述使用Redis-cli连接Redis服务,因为工具无法直接支持TLS6380端口连接,所以需要使用stunnel配置TLS/SSL服务。根据文章(LinuxVM使用6380端口(SSL方式)连接AzureRedis(redis-cli&stunnel):https://www.cnblogs.com/lulight/p/14188279.html),配置stunnel后,始终......