代码示例

最近更新时间:2025-07-01 11:17:01

我的收藏

Pom 配置

<!-- 引入spring-data-redis组件,默认已集成Lettuce依赖SDK -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0.RELEASE</version>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>4.1.100.Final</version>
<classifier>linux-x86_64</classifier>
</dependency>

配置代码

说明:
配置 Lettuce 连接池的 LIFO = false(即采用 FIFO 队列模式),否则在云环境 VIP 场景下会因连接响应时间差异导致负载不均,连接池失效的问题。
1. 默认的 LIFO(后进先出)模式会优先复用最新归还的连接,使部分响应快的连接成为“热连接”,而响应慢的连接长期闲置,导致后端实际负载倾斜。
2. 连接池失效:当某条连接因响应慢被暂时弃用,LIFO 机制会加剧新请求集中分配给少数活跃连接,放大单点瓶颈风险。

import java.time.Duration;

import org.springframework.beans.factory.annotation.Value;
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.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;

@Configuration
public class lettuceSingleConfig {
// @Value("${tencent.redis.host}")
// private String redisHost;
//
// @Value("${tencent.redis.port:6379}")
// private Integer redisPort = 6379;
//
// @Value("${tencent.redis.database:0}")
// private Integer redisDatabase = 0;
//
// @Value("${tencent.redis.password:}")
// private String redisPassword;

@Value("${tencent.redis.connect.timeout:2000}")
private Integer redisConnectTimeout = 2000;

@Value("${tencent.redis.command.timeout:2000}")
private Integer redisCommandTimeout = 2000;
/**
* TCP_KEEPALIVE 配置参数
*/
@Value("${tencent.redis.tcp.keepalive.time.idle:30}")
private Integer redisTcpKeepaliveTimeIdle = 30;
@Value("${tencent.redis.tcp.keepalive.time.interval:10}")
private Integer redisTcpKeepaliveTimeInterval = 10;
@Value("${tencent.redis.tcp.keepalive.count:3}")
private Integer redisTcpKeepaliveCount = 3;

/**
* TCP_USER_TIMEOUT 解决Lettuce长时间超时问题
*/
@Value("${tencent.redis.tcp.user.timeout:30}")
private Integer redisTcpUserTimeout = 30;

/**
* pool相关参数
*/
@Value("${tencent.redis.pool.max-wait:1000}")
private Integer RedisPoolMaxwait = 1000;
@Value("${tencent.redis.pool.max-active:2000}")
private Integer RedisPoolMaxTotal = 2000;
@Value("${tencent.redis.pool.max-idle:1000}")
private Integer RedisPoolMaxIdle = 1000;
@Value("${tencent.redis.pool.min-idle:500}")
private Integer RedisPoolMinIdle = 500;

/**
* redisConnectionFactory以及相关参数(Host、Port、Database、Password)与 application.properties 配置方式二选一
*/
// @Bean
// public LettuceConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) {
//
// RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
// standaloneConfiguration.setHostName(redisHost);
// standaloneConfiguration.setPort(redisPort);
// standaloneConfiguration.setDatabase(redisDatabase);
// standaloneConfiguration.setPassword(redisPassword);
//
// LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration);
// connectionFactory.setDatabase(redisDatabase);
// return connectionFactory;
// }

@Bean
public LettuceClientConfiguration clientConfiguration() {


SocketOptions socketOptions = SocketOptions.builder()
.keepAlive(SocketOptions.KeepAliveOptions.builder()
// 连接空闲多久开始 keepalive
.idle(Duration.ofSeconds(redisTcpKeepaliveTimeIdle))
// 两次 keepalive 间的时间间隔
.interval(Duration.ofSeconds(redisTcpKeepaliveTimeInterval))
// keepalive 几次之后断开连接
.count(redisTcpKeepaliveCount)
// 是否开启保活连接
.enable()
.build())
.tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
// 解决服务端rst导致的长时间超时问题
.tcpUserTimeout(Duration.ofSeconds(redisTcpUserTimeout))
.enable()
.build())
// tcp 连接超时设置
.connectTimeout(Duration.ofMillis(redisConnectTimeout))
.build();

ClientOptions clientOptions = ClientOptions.builder()
.autoReconnect(true)
.pingBeforeActivateConnection(true)
.cancelCommandsOnReconnectFailure(false)
.disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS)
.socketOptions(socketOptions)
.build();

// 创建连接池配置并关闭LIFO
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setLifo(false); // 关闭LIFO,启用FIFO模式
poolConfig.setMaxTotal(RedisPoolMaxTotal); // 可选:设置最大连接数
poolConfig.setMaxIdle(RedisPoolMaxIdle); // 可选:设置最大空闲连接数
poolConfig.setMinIdle(RedisPoolMinIdle); // 可选:设置最小空闲连接数
poolConfig.setMaxWait(Duration.ofMillis(RedisPoolMaxwait));

return LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig)
.commandTimeout(Duration.ofMillis(redisCommandTimeout))
.clientOptions(clientOptions)
.build();
}
}