Springboot整合Redis主從
- 前言
- 原配置
- 現配置
- 測試
- LettuceConnectionFactory.setShareNativeConnection 方法的作用
前言
SpringBoot版本:2.3.2.RELEASE
原配置
原yml配置內容:
spring:# Redis服務器配置redis:host: 127.0.0.1# Redis服務器連接端口port: 6379# Redis服務器連接密碼password: redis@123#連接超時時間(毫秒)timeout: 30000msjedis:# Redis服務器連接池pool:# 連接池最大連接數(使用負值表示沒有限制)maxIdle: 400#連接池中的最小空閑連接minIdle: 100#連接池中的最大空閑連接maxActive: 400# 連接池最大阻塞等待時間(使用負值表示沒有限制)maxWait: -1mslettuce:pool:max-idle: 400min-idle: 100max-active: 400max-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.1port: 6379password: redis@123# 副本節點replicas:- host: 127.0.0.1port: 6380#連接超時時間(毫秒)timeout: 30000msjedis:# Redis服務器連接池pool:# 連接池最大連接數(使用負值表示沒有限制)maxIdle: 400#連接池中的最小空閑連接minIdle: 100#連接池中的最大空閑連接maxActive: 400# 連接池最大阻塞等待時間(使用負值表示沒有限制)maxWait: -1mslettuce:pool:max-idle: 400min-idle: 100max-active: 400max-wait: -1ms
現RedisConfig配置類:
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.juxiao.xchat.manager.cache.properties.RedisMasterReplicaProperties;
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;}@Beanpublic LettuceConnectionFactory redisConnectionFactory() {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(ReadFrom.REPLICA_PREFERRED);LettucePoolingClientConfiguration lettucePoolingClientConfiguration = builder.build();// 構建連接工廠LettuceConnectionFactory factory = new LettuceConnectionFactory(config, lettucePoolingClientConfiguration);// 禁用共享連接 默認是true// factory.setShareNativeConnection(false);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(value = StringRedisTemplate.class, name = "stringRedisTemplate")public StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);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<>();@Datapublic static class Node {/*** 主機地址*/private String host;/*** 端口*/private int port;/*** 密碼(主從模式master、slave密碼必須設置一樣的)*/private String password;}
}
測試
@Autowiredprivate StringRedisTemplate redisTemplate;@GetMapping("/test")public String test() {ValueOperations<String, String> opsedForValue = redisTemplate.opsForValue();opsedForValue.set("imu:test", "Hello6");String value = opsedForValue.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: -1mslettuce:pool:max-idle: 400min-idle: 100max-active: 400max-wait: -1ms