帮你快速理解、总结文档立即下载

Java 连接示例

最近更新时间:2026-10-20 11:39:01
本文档已由 AI 辅助审校
我的收藏
本文介绍使用 Java 客户端通过代理模式和直连模式连接腾讯云分布式缓存数据库实例的示例。

准备工作

环境要求

JDK 8及以上版本。
Maven 或 Gradle 构建工具。

添加依赖

Maven 依赖
<!-- Jedis 客户端(推荐 5.1.2 及以上版本) -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.2</version>
</dependency>

<!-- Lettuce 客户端(推荐 6.3.0 及以上版本) -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0.RELEASE</version>
</dependency>
Gradle 依赖
implementation 'redis.clients:jedis:5.1.2'
implementation 'io.lettuce:lettuce-core:6.3.0.RELEASE'

获取连接信息

2. 在实例列表中,单击目标实例 ID,进入实例详情页。
3. 在网络信息区域,获取实例的连接地址和端口号。
代理模式:获取 VIP 地址和端口(默认6379)。
直连模式:获取各分片节点地址和端口(默认6379)。
4. 在配置信息区域,获取实例的连接密码。代理模式与直连模式的认证方式不同:
代理模式:默认账号使用 实例 ID:密码 格式,自定义账号使用 用户名@密码 格式;免密认证实例无需密码。
直连模式:复用 Redis 原生 ACL 认证机制,不支持 用户名@密码 拼接格式,支持以下两种认证方式:
默认账号:仅需密码,即 AUTH password。
自定义账号:需同时指定账号名与密码,即 AUTH account password。

代理模式连接示例

代理模式下,客户端通过 Proxy 代理层提供的统一 VIP 地址连接实例,Proxy 自动处理请求路由和故障转移,客户端无需感知后端拓扑变化。
说明:
代理模式服务端支持多 DB(默认分配256个 DB),但 Jedis 因自身实现限制可能无法使用 SELECT 命令切换数据库,此时只能使用 DB0。如业务依赖多 DB,请改用支持 SELECT 命令的客户端。

Jedis 连接池示例(推荐)

使用 JedisPool 连接池管理连接,推荐配置 FIFO 模式避免负载不均。
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;

public class JedisProxyExample {
public static void main(String[] args) {
// 连接参数
String host = "192.xx.xx.2"; // 实例 VIP 地址
int port = 6379; // 实例端口
String password = "crs-xxxx:密码"; // 默认账号密码格式:实例ID:密码

// 连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200); // 最大连接数
poolConfig.setMaxIdle(200); // 最大空闲连接数
poolConfig.setMinIdle(50); // 最小空闲连接数
poolConfig.setMaxWaitMillis(3000); // 获取连接最大等待时间(毫秒)
poolConfig.setTestOnBorrow(false); // 获取连接时不测试
poolConfig.setTestOnReturn(false); // 归还连接时不测试
poolConfig.setTestWhileIdle(true); // 空闲时测试连接有效性
poolConfig.setLifo(false); // 关闭 LIFO,使用 FIFO 避免负载不均

// 创建连接池
JedisPool jedisPool = new JedisPool(
poolConfig,
host,
port,
2000, // 连接超时(毫秒)
2000, // 读取超时(毫秒)
password
);

// 使用连接池执行操作
try (Jedis jedis = jedisPool.getResource()) {
// 写入数据
jedis.set("name", "腾讯云分布式缓存数据库");
// 读取数据
String value = jedis.get("name");
System.out.println("get name: " + value);

// 设置带过期时间的 Key
jedis.setex("session:user123", 3600, "session_data");

// 哈希操作
jedis.hset("user:1001", "name", "张三");
jedis.hset("user:1001", "age", "28");
System.out.println("user name: " + jedis.hget("user:1001", "name"));

// 列表操作
jedis.lpush("queue:tasks", "task1", "task2", "task3");
String task = jedis.rpop("queue:tasks");
System.out.println("dequeued task: " + task);
}

// 应用关闭时销毁连接池
jedisPool.close();
}
}

Jedis 自定义账号连接示例

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;

public class JedisCustomAccountExample {
public static void main(String[] args) {
String host = "192.xx.xx.2";
int port = 6379;
String password = "myuser@MyPassword"; // 代理模式自定义账号:用户名@密码整体作为密码传入(区别于直连模式 ACL 的账号名/密码分离传参)

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setLifo(false);

// 代理模式自定义账号:将“用户名@密码”作为整体密码传入,不单独设置用户名
JedisPool jedisPool = new JedisPool(
poolConfig,
host,
port,
2000,
2000,
password // 用户名@密码
);

try (Jedis jedis = jedisPool.getResource()) {
jedis.set("key", "value");
System.out.println(jedis.get("key"));
}

jedisPool.close();
}
}

Spring Boot + Jedis 集成示例

application.yml 配置
spring:
redis:
host: 192.xx.xx.2
port: 6379
password: crs-xxxx:密码
timeout: 2000ms
jedis:
pool:
max-active: 200
max-idle: 200
min-idle: 50
max-wait: 3000ms
配置类
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.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

@Configuration
public class RedisConfig {

@Bean
public JedisConnectionFactory jedisConnectionFactory() {
// 单机配置
RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();
standaloneConfig.setHostName("192.xx.xx.2");
standaloneConfig.setPort(6379);
standaloneConfig.setPassword("crs-xxxx:密码");

// 连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false); // FIFO 模式

// 客户端配置
JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
.connectTimeout(Duration.ofMillis(2000))
.readTimeout(Duration.ofMillis(2000))
.usePooling()
.poolConfig(poolConfig)
.build();

return new JedisConnectionFactory(standaloneConfig, clientConfig);
}

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}

Lettuce 连接示例(推荐)

Lettuce 是基于 Netty 的异步 Redis 客户端,推荐使用6.3.0及以上版本,并配置 TCP Keepalive 和 tcpUserTimeout 参数。
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.support.ConnectionPoolSupport;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.time.Duration;

public class LettuceProxyExample {
public static void main(String[] args) {
// 构建 RedisURI
RedisURI redisUri = RedisURI.builder()
.withHost("192.xx.xx.2")
.withPort(6379)
.withPassword("crs-xxxx:密码".toCharArray())
.withTimeout(Duration.ofSeconds(2))
.build();

// Socket 配置(关键参数)
SocketOptions socketOptions = SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(2)) // 连接超时
.keepAlive(SocketOptions.KeepAliveOptions.builder()
.enable() // 开启 TCP Keepalive
.idle(Duration.ofSeconds(30)) // 空闲 30 秒开始探测
.interval(Duration.ofSeconds(10)) // 探测间隔 10 秒
.count(3) // 探测次数 3 次
.build())
.tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
.enable() // 开启 tcpUserTimeout
.tcpUserTimeout(Duration.ofSeconds(30)) // 30 秒超时
.build())
.build();

// 创建 RedisClient
RedisClient redisClient = RedisClient.create();
redisClient.setOptions(io.lettuce.core.ClientOptions.builder()
.socketOptions(socketOptions)
.build());

// 连接池配置
GenericObjectPoolConfig<StatefulRedisConnection<String, String>> poolConfig =
new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false); // FIFO 模式

// 创建连接池
GenericObjectPool<StatefulRedisConnection<String, String>> pool =
ConnectionPoolSupport.createGenericObjectPool(
() -> redisClient.connect(redisUri),
poolConfig
);

// 使用连接池执行操作
try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
RedisCommands<String, String> sync = connection.sync();
sync.set("name", "腾讯云分布式缓存数据库");
String value = sync.get("name");
System.out.println("get name: " + value);

sync.hset("user:1001", "name", "张三");
sync.hset("user:1001", "age", "28");
System.out.println("user name: " + sync.hget("user:1001", "name"));
} catch (Exception e) {
e.printStackTrace();
}

// 应用关闭时清理资源
pool.close();
redisClient.shutdown();
}
}

Spring Boot + Lettuce 集成示例

application.yml 配置
spring:
redis:
host: 192.xx.xx.2
port: 6379
password: crs-xxxx:密码
timeout: 2000ms
lettuce:
pool:
max-active: 200
max-idle: 200
min-idle: 50
max-wait: 3000ms
配置类(含 TCP Keepalive 和 tcpUserTimeout)
import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
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.LettuceClientConfiguration;
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.serializer.StringRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.time.Duration;

@Configuration
public class LettuceRedisConfig {

@Bean(destroyMethod = "shutdown")
public ClientResources clientResources() {
return DefaultClientResources.create();
}

@Bean
public LettuceConnectionFactory lettuceConnectionFactory(ClientResources clientResources) {
// Socket 配置
SocketOptions socketOptions = SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(2))
.keepAlive(SocketOptions.KeepAliveOptions.builder()
.enable()
.idle(Duration.ofSeconds(30))
.interval(Duration.ofSeconds(10))
.count(3)
.build())
.tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
.enable()
.tcpUserTimeout(Duration.ofSeconds(30))
.build())
.build();

ClientOptions clientOptions = ClientOptions.builder()
.socketOptions(socketOptions)
.build();

// 连接池配置
GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false);

// Lettuce 客户端配置
LettucePoolingClientConfiguration lettuceConfig =
LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(2))
.clientOptions(clientOptions)
.clientResources(clientResources)
.poolConfig(poolConfig)
.build();

// 创建连接工厂
org.springframework.data.redis.connection.RedisStandaloneConfiguration standaloneConfig =
new org.springframework.data.redis.connection.RedisStandaloneConfiguration();
standaloneConfig.setHostName("192.xx.xx.2");
standaloneConfig.setPort(6379);
standaloneConfig.setPassword("crs-xxxx:密码");

return new LettuceConnectionFactory(standaloneConfig, lettuceConfig);
}

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}

SSL 加密连接示例(Jedis)

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.security.KeyStore;

public class JedisSSLExample {
public static void main(String[] args) throws Exception {
String host = "192.xx.xx.2";
int port = 6379;
String password = "crs-xxxx:密码";

// 加载 CA 证书(JKS 格式)
KeyStore trustStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream("/path/to/ca.jks")) {
trustStore.load(fis, "password".toCharArray());
}

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

// 连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setLifo(false);

// 创建 SSL 连接池
JedisPool jedisPool = new JedisPool(
poolConfig,
host,
port,
2000,
2000,
password,
true, // 启用 SSL
sslContext.getSocketFactory(),
null, // SSL 参数
null // 主机名验证器
);

try (Jedis jedis = jedisPool.getResource()) {
jedis.set("ssl_test", "encrypted");
System.out.println(jedis.get("ssl_test"));
}

jedisPool.close();
}
}

直连模式连接示例

直连模式下,客户端使用 Redis Cluster 协议直接连接各分片节点,本地处理 MOVED/ASK 重定向,可直接使用社区标准的 Redis Cluster 客户端接入。
说明:
直连模式仅适用于集群架构实例。
需使用支持 Redis Cluster 协议的客户端(JedisCluster 或 Lettuce RedisClusterClient)。
需在控制台开启直连模式并获取各分片节点的连接地址。
认证方式复用 Redis 原生 ACL 机制:默认账号仅传密码,自定义账号需分别传入账号名与密码,不支持 用户名@密码 拼接格式。
直连模式暂不支持 SSL 加密连接。

JedisCluster 连接示例(推荐)

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

public class JedisClusterExample {
public static void main(String[] args) {
// 直连模式下各分片节点地址
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.xx.xx.2", 6379));
nodes.add(new HostAndPort("192.xx.xx.3", 6379));
nodes.add(new HostAndPort("192.xx.xx.4", 6379));

String password = "password"; // 直连模式默认账号仅传密码,不带实例 ID 前缀

// 连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false);

// 创建 JedisCluster
JedisCluster jedisCluster = new JedisCluster(
nodes,
2000, // 连接超时(毫秒)
2000, // 读取超时(毫秒)
3, // 最大重试次数
password,
poolConfig
);

// 写入数据(客户端自动路由到正确的分片)
jedisCluster.set("cluster:key1", "value1");
jedisCluster.set("cluster:key2", "value2");
jedisCluster.set("cluster:key3", "value3");

// 读取数据
System.out.println("key1: " + jedisCluster.get("cluster:key1"));
System.out.println("key2: " + jedisCluster.get("cluster:key2"));
System.out.println("key3: " + jedisCluster.get("cluster:key3"));

// 哈希操作
jedisCluster.hset("user:{1001}", "name", "张三");
jedisCluster.hset("user:{1001}", "age", "28");
System.out.println("user name: " + jedisCluster.hget("user:{1001}", "name"));

// 使用 Hash Tag 确保相关 Key 路由到同一分片
jedisCluster.set("{order:1001}:status", "paid");
jedisCluster.set("{order:1001}:amount", "99.00");
jedisCluster.set("{order:1001}:time", "2025-01-01 10:00:00");
System.out.println("order status: " + jedisCluster.get("{order:1001}:status"));

// 应用关闭时关闭集群连接
jedisCluster.close();
}
}

JedisCluster 自定义账号(ACL)连接示例

直连模式复用 Redis 原生 ACL 认证机制,使用自定义账号时需分别传入账号名与密码,不支持 用户名@密码 拼接格式。
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

public class JedisClusterAclExample {
public static void main(String[] args) {
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.xx.xx.2", 6379));
nodes.add(new HostAndPort("192.xx.xx.3", 6379));
nodes.add(new HostAndPort("192.xx.xx.4", 6379));

// ===== ACL 认证机制:账号名与密码是两个独立字段 =====
// 直连模式的多账号能力基于 Redis 原生 ACL:控制台创建的每个自定义账号
// 都是一个独立的 ACL user,认证时客户端向节点发送 AUTH <account> <password>。
String user = "myuser"; // ACL 账号名 → 对应 AUTH 的 <account>
String password = "MyPassword"; // 该账号的密码 → 对应 AUTH 的 <password>(纯密码,无需拼接)

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setLifo(false);

// 将 user 与 password 分别传入(等价于执行 AUTH account password);
// 注意:不要写成代理模式的 "myuser@MyPassword" 拼接格式。
JedisCluster jedisCluster = new JedisCluster(
nodes,
2000, // 连接超时(毫秒)
2000, // 读取超时(毫秒)
3, // 最大重试次数
user, // ACL 账号名 → AUTH account
password, // 账号密码 → AUTH password
"clientName", // 客户端名称
poolConfig
);

jedisCluster.set("key", "value");
System.out.println(jedisCluster.get("key"));

jedisCluster.close();
}
}

Lettuce RedisClusterClient 连接示例

import io.lettuce.core.RedisURI;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;

import java.time.Duration;
import java.util.Arrays;

public class LettuceClusterExample {
public static void main(String[] args) {
// 构建集群节点 URI 列表
RedisURI node1 = RedisURI.builder()
.withHost("192.xx.xx.2").withPort(6379)
.withPassword("password".toCharArray())
.build();
RedisURI node2 = RedisURI.builder()
.withHost("192.xx.xx.3").withPort(6379)
.withPassword("password".toCharArray())
.build();
RedisURI node3 = RedisURI.builder()
.withHost("192.xx.xx.4").withPort(6379)
.withPassword("password".toCharArray())
.build();

// Socket 配置
SocketOptions socketOptions = SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(2))
.keepAlive(SocketOptions.KeepAliveOptions.builder()
.enable()
.idle(Duration.ofSeconds(30))
.interval(Duration.ofSeconds(10))
.count(3)
.build())
.tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
.enable()
.tcpUserTimeout(Duration.ofSeconds(30))
.build())
.build();

// 集群客户端配置
ClusterClientOptions clusterOptions = ClusterClientOptions.builder()
.socketOptions(socketOptions)
.maxRedirects(3) // 最大重定向次数
.validateClusterNodeMembership(true)
.build();

// 创建 RedisClusterClient
RedisClusterClient clusterClient = RedisClusterClient.create(
Arrays.asList(node1, node2, node3));
clusterClient.setOptions(clusterOptions);

// 获取集群连接
StatefulRedisClusterConnection<String, String> connection =
clusterClient.connect();

// 执行操作
RedisAdvancedClusterCommands<String, String> sync = connection.sync();

sync.set("cluster:key1", "value1");
sync.set("cluster:key2", "value2");
System.out.println("key1: " + sync.get("cluster:key1"));
System.out.println("key2: " + sync.get("cluster:key2"));

// 使用 Hash Tag
sync.set("{order:1001}:status", "paid");
sync.set("{order:1001}:amount", "99.00");
System.out.println("order status: " + sync.get("{order:1001}:status"));

// 关闭连接
connection.close();
clusterClient.shutdown();
}
}

Spring Boot + JedisCluster 集成示例

配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

@Configuration
public class JedisClusterConfig {

@Bean
public JedisCluster jedisCluster() {
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.xx.xx.2", 6379));
nodes.add(new HostAndPort("192.xx.xx.3", 6379));
nodes.add(new HostAndPort("192.xx.xx.4", 6379));

JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false);

return new JedisCluster(
nodes,
2000,
2000,
3,
"password",
poolConfig
);
}
}

Spring Boot + Lettuce Cluster 集成示例

application.yml 配置
spring:
redis:
cluster:
nodes:
- 192.xx.xx.2:6379
- 192.xx.xx.3:6379
- 192.xx.xx.4:6379
password: password
timeout: 2000ms
lettuce:
pool:
max-active: 200
max-idle: 200
min-idle: 50
max-wait: 3000ms
配置类(含 TCP Keepalive 和 tcpUserTimeout)
import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
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.serializer.StringRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.time.Duration;

@Configuration
public class LettuceClusterConfig {

@Bean(destroyMethod = "shutdown")
public ClientResources clientResources() {
return DefaultClientResources.create();
}

@Bean
public LettuceConnectionFactory lettuceConnectionFactory(ClientResources clientResources) {
// 集群节点配置
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration();
clusterConfig.clusterNode("192.xx.xx.2", 6379);
clusterConfig.clusterNode("192.xx.xx.3", 6379);
clusterConfig.clusterNode("192.xx.xx.4", 6379);
clusterConfig.setPassword("password");

// Socket 配置
SocketOptions socketOptions = SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(2))
.keepAlive(SocketOptions.KeepAliveOptions.builder()
.enable()
.idle(Duration.ofSeconds(30))
.interval(Duration.ofSeconds(10))
.count(3)
.build())
.tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
.enable()
.tcpUserTimeout(Duration.ofSeconds(30))
.build())
.build();

ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
.socketOptions(socketOptions)
.maxRedirects(3)
.build();

// 连接池配置
GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(200);
poolConfig.setMinIdle(50);
poolConfig.setMaxWaitMillis(3000);
poolConfig.setLifo(false);

LettucePoolingClientConfiguration lettuceConfig =
LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(2))
.clientOptions(clusterClientOptions)
.clientResources(clientResources)
.poolConfig(poolConfig)
.build();

return new LettuceConnectionFactory(clusterConfig, lettuceConfig);
}

@Bean
public RedisTemplate<String, String> redisTemplate(LettuceConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}

关键参数说明

Jedis 连接池参数

参数
说明
推荐值
maxTotal
最大连接数
200
maxIdle
最大空闲连接数
200
minIdle
最小空闲连接数
50
maxWaitMillis
获取连接最大等待时间(毫秒)
3000
lifo
连接获取策略
false(FIFO,避免负载不均)
connectTimeout
连接超时(毫秒)
2000
readTimeout
读取超时(毫秒)
2000

Lettuce TCP Keepalive 参数

参数
说明
推荐值
keepAlive.idle
空闲多久开始探测
30 秒
keepAlive.interval
探测间隔
10 秒
keepAlive.count
探测次数
3 次
tcpUserTimeout
TCP 用户超时
30 秒
说明:
TCP Keepalive 和 tcpUserTimeout 是连接腾讯云分布式缓存数据库的必要配置:
TCP Keepalive:当主备切换时,VIP 发生漂移,旧连接变为死连接。若不开启 Keepalive,客户端无法感知连接中断,导致请求超时。
tcpUserTimeout:当节点被动宕机时,TCP 连接无法正常关闭,若不设置 tcpUserTimeout,僵尸连接会持续占用资源长达30分钟以上。

常见问题

连接超时

确认客户端所在 CVM 与分布式缓存数据库实例在同一 VPC 内。
确认安全组规则已放通对应端口。
确认连接地址和端口正确。

认证失败

代理模式:默认账号使用 实例 ID:密码,自定义账号使用 用户名@密码。
直连模式:复用 Redis ACL 认证,默认账号仅传密码(AUTH password),自定义账号需分别传入账号名与密码(AUTH account password),不支持 用户名@密码 拼接格式。
确认密码中无特殊字符导致解析异常。

直连模式 MOVED 错误

确认使用 JedisCluster 或 RedisClusterClient 而非 Jedis 或 RedisClient。
确认已在控制台开启直连模式。
确认 seeds 地址为分片节点地址而非 VIP 地址。

Lettuce 连接池获取连接超时

检查 maxTotal 和 maxIdle 是否设置合理。
确认 lifo 设置为 false(FIFO 模式)。
确认 minIdle 设置合理,避免冷连接建立开销。