当前位置: 代码网 > it编程>编程语言>Java > Springboot整合Redis主从实践

Springboot整合Redis主从实践

2025年06月12日 Java 我要评论
前言springboot版本:2.3.2.release原配置原yml配置内容:spring: # redis服务器配置 redis: host: 127.0.0.1 # redis服

前言

springboot版本:2.3.2.release

原配置

原yml配置内容:

spring:
  # redis服务器配置
  redis:
    host: 127.0.0.1
    # redis服务器连接端口
    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:
        # 连接池最大连接数(使用负值表示没有限制)
        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.conditionalonmissingbean;
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.context.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 stringredisserializer());
        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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com