本文介绍使用 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'
获取连接信息
1. 登录 分布式缓存数据库控制台。
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);// 设置带过期时间的 Keyjedis.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.2port: 6379password: crs-xxxx:密码timeout: 2000msjedis:pool:max-active: 200max-idle: 200min-idle: 50max-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;@Configurationpublic class RedisConfig {@Beanpublic 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);}@Beanpublic 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) {// 构建 RedisURIRedisURI 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();// 创建 RedisClientRedisClient 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.2port: 6379password: crs-xxxx:密码timeout: 2000mslettuce:pool:max-active: 200max-idle: 200min-idle: 50max-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;@Configurationpublic class LettuceRedisConfig {@Bean(destroyMethod = "shutdown")public ClientResources clientResources() {return DefaultClientResources.create();}@Beanpublic 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);}@Beanpublic 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, // 启用 SSLsslContext.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);// 创建 JedisClusterJedisCluster 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 accountpassword, // 账号密码 → 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();// 创建 RedisClusterClientRedisClusterClient 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 Tagsync.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;@Configurationpublic class JedisClusterConfig {@Beanpublic 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:6379password: passwordtimeout: 2000mslettuce:pool:max-active: 200max-idle: 200min-idle: 50max-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;@Configurationpublic class LettuceClusterConfig {@Bean(destroyMethod = "shutdown")public ClientResources clientResources() {return DefaultClientResources.create();}@Beanpublic 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);}@Beanpublic 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 设置合理,避免冷连接建立开销。