前言
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总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论