Springboot整合Redis主从实践

2025-06-12 15:50

本文主要是介绍Springboot整合Redis主从实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Springboot整合Redis主从实践》:本文主要介绍Springboot整合Redis主从的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教...

前言

SpringBoot版本:2.3.2.RELEASE

原配置

原yml配置内容:

spring:
  # Redis服务器配置
  redis:
    host: 127.0.0.1
    # Redis服务器连接端口
   fLDsJoaSkC port: 6379
    # Redis服务器连接密码
    password: redis@123
    #连接超时时间(毫秒)
    timeout: 30000ms
    jedis:
      # Redis服务器连接池
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        maxIdle: 400
        #连接池中的最小空闲连接
        minIdle: 100
        #连接池中的最大空闲连接
        maxActive: 400
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        maxWait: -1ms
    lettuce:
      pool:
        max-idle: 400
        min-idle: 100
        max-active: 400
        max-wait: -1ms

原RedisConfig配置类:

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {

    @Bean
    @ConditionalOnMissingBean(value = StringRedisTemplate.class, name = "stringRedisTemplate")
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        return template;
    }
}

现配置

现yml配置内容:

spring:
  redis:
    # 主节点
    master:
      host: 127.0.0.1
      port: 6379
      password: redis@123
    # 副本节点
    replicas:
      - host: 127.0.0.1
        port: 6380
    #连接超时时间(毫秒)
    timeout: 30000ms
    jedis:
      # Redis服务器连接池
      pool:
        # 连接js池最大连接数(使用负值表示没有限制)
        maxIdle: 400
        #连接池中的最小空闲连接
        minIdle: 100
        #连接池中的最大空闲连接
        maxActive: 400
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        maxWait: -1ms
    lettuce:
      pool:
        max-idle: 400
        min-idle: 100
        max-active: 400
        max-wait: -1ms

现RedisConfig配置类:

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.juxiao.xchat.manager.cache.properties.RedisMasterReplicaProperties;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.ReadFrom;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.Chttp://www.chinasem.cnonditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.co编程ntext.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableConfigurationProperties({RedisMasterReplicaProperties.class, RedisProperties.class})
public class RedisConfig {

    private final RedisMasterReplicaProperties properties;
    private final RedisProperties redisProperties;

    public RedisConfig(RedisMasterReplicaProperties redisMasterReplicaProperties, RedisProperties redisProperties) {
        this.properties = redisMasterReplicaProperties;
        this.redisProperties = redisProperties;
    }

    public LettuceConnectionFactory redisConnectionFactory(boolean readFromMaster) {
        RedisStaticMasterReplicaConfiguration config = new RedisStaticMasterReplicaConfiguration(
                properties.getMaster().getHost(), properties.getMaster().getPort()
        );
        String password = properties.getMaster().getPassword();
        if (StringUtils.isNotBlank(password)) {
            config.setPassword(RedisPassword.of(password));
        }
        for (RedisMasterReplicaProperties.Node replica : properties.getReplicas()) {
            config.addNode(replica.getHost(), replica.getPort());
        }

        // 连接池配置
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder =
                LettucePoolingClientConfiguration.builder().commandTimeout(redisProperties.getTimeout());
        // 使用 application.yml 中的 lettuce.pool 参数
        RedisProperties.Pool poolProps = redisProperties.getLettuce().getPool();
        if (poolProps != null) {
            builder.poolConfig(poolConfig(poolProps));
        }
        // 优先从副本读取
        builder.readFrom(readFromMaster ? ReadFrom.MASTER : ReadFrom.REPLICA_PREFERRED);
        // 断开连接时拒绝命令[而不是再等待连接超时时间后再报错]、启用自动重连
        builder.clientOptions(ClientOptions.builder()
                .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
                .autoReconnect(true)
                .build());
        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = builder.build();
        // 构建连接工厂
        LettuceConnectionFactory factory = new LettuceConnectionFactory(config, lettucePoolingClientConfiguration);
        // 禁用共享连接 默认是true
        // factory.setShareNativeConnection(false);
        // 初始化工厂 否则调用StringRedisTemplate时会空指针 【因为redisConnectionFactory 方法没有使用@Bean注解将LettuceConnectionFactory交给Spring工厂管理 所以需要手动调用afterPropertiesSet方法初始化连接工厂】
        factory.afterPropertiesSet();
        return factory;
    }

    // 连接池参数绑定
    private GenericObjectPoolConfig<?> poolConfig(RedisProperties.Pool poolProps) {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(poolProps.getMaxActive());
        config.setMaxIdle(poolProps.getMaxIdle());
        config.setMinIdle(poolProps.getMinIdle());
        config.setMaxWaitMillis(poolProps.getMaxWait().toMillis());
        return config;
    }

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        redisConnectionFactory.setShareNativeConnection(false);
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        //使用fastjson序列化
        FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class);
        // value值的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializepythonr());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean("masterStringRedisTemplate")
    @ConditionalOnMissingBean(name = "masterStringRedisTemplate")
    public StringRedisTemplate masterStringRedisTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory(true));
        return template;
    }

    @Bean("replicaStringRedisTemplate")
    @ConditionalOnMissingBean(name = "replicaStringRedisTemplate")
    public StringRedisTemplate replicaStringRedisTemplate() {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory(false));
        return template;
    }
}

新增RedisMasterReplicaProperties配置类:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import Java.util.ArrayList;
import java.util.List;

@Data
@ConfigurationProperties(prefix = "spring.redis")
public class RedisMasterReplicaProperties {

    /**
     * 主节点
     */
    private Node master;
    /**
     * 从节点
     */
    private List<Node> replicas = new ArrayList<>();

    @Data
    public static class Node {
        /**
         * 主机地址
         */
        private String host;
        /**
         * 端口
         */
        private int port;
        /**
         * 密码(主从模式master、slave密码必须设置一样的)
         */
        private String password;
    }
}

测试

    @Resource(name = "masterStringRedisTemplate")
    private StringRedisTemplate masterStringRedisTemplate;
    @Resource(name = "replicaStringRedisTemplate")
    private StringRedisTemplate replicaStringRedisTemplate;

    @GetMapping("/test")
    public String test() {
        
        masterStringRedisTemplate.opsForValue().set("imu:test", "Hello6");

        String value = replicaStringRedisTemplate.opsForValue().get("imu:test");
        return value;
    }

LettuceConnectionFactory.setShareNativeConnection 方法的作用

代码中这一行被注释,保持了原本的默认配置true

// 禁用共享连接 默认是true
// factory.setShareNativeConnection(false);

在 Spring Data Redis 中,LettuceConnectionFactory 是一个用于管理 Redis 连接的工厂类,而 setShareNativeConnection(boolean shareNativeConnection) 方法用于控制是否 共享底层的 Redis 连接。

true(默认):

  • 适用于 大多数应用,多个 Redis 操作共享同一个底层连接,减少资源占用。
  • 适用于 Spring Boot + RedisTemplate 场景。

false:

  • 适用于 高并发、多线程环境,避免多个线程争抢同一个 Redis 连接。
  • 适用于 WebFlux、Reactive、Pipeline 等场景。

一般来说,除非你的 Redis 操作出现 多线程连接争用问题,否则 不用手动修改 setShareNativeConnection,保持默认值即可!

而:

  • shareNativeConnection = true
  • (默认)时,Spring 只会创建 一个共享的 StatefulRedisConnection,那么 连接池的 max-active、max-idle、min-idle 这些配置不会生效。
  • shareNativeConnection = false 时,每次请求都会新建连接,这时连接池才会管理多个连接,此时 max-active 等参数才会起作用。
  • 也就是说我们在yml配置文件中配置的连接池信息都将不起作用
    jedis:
      # Redis服务器连接池
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        maxIdle: 400
        #连接池中的最小空闲连接
        minIdle: 100
        #连接池中的最大空闲连接
        maxActive: 400
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        maxWait: -1ms
    lettuce:
      pool:
        max-idle: 400
        min-idle: 100
        max-active: 400
        max-wait: -1ms

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于Springboot整合Redis主从实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155027

相关文章

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Java SWT库详解与安装指南(最新推荐)

《JavaSWT库详解与安装指南(最新推荐)》:本文主要介绍JavaSWT库详解与安装指南,在本章中,我们介绍了如何下载、安装SWTJAR包,并详述了在Eclipse以及命令行环境中配置Java... 目录1. Java SWT类库概述2. SWT与AWT和Swing的区别2.1 历史背景与设计理念2.1.

使用SpringBoot整合Sharding Sphere实现数据脱敏的示例

《使用SpringBoot整合ShardingSphere实现数据脱敏的示例》ApacheShardingSphere数据脱敏模块,通过SQL拦截与改写实现敏感信息加密存储,解决手动处理繁琐及系统改... 目录痛点一:痛点二:脱敏配置Quick Start——Spring 显示配置:1.引入依赖2.创建脱敏