#如何访问集群实例
本指南演示如何使用业界标准客户端库连接 Redis Cluster 实例。示例涵盖了 go-redis、Jedis、Lettuce 和 Redisson 的配置细节。更多客户端选项,请参阅 Connect with Redis client API libraries。
#目录
#认证要求
Redis Cluster 实例支持以下认证选项:
- 密码认证:配置密码后,所有客户端连接必须提供有效凭据
- 无密码访问:如果实例创建时未启用 Set Password 选项,客户端可无认证连接
安全最佳实践
生产环境强烈建议启用密码认证以保护数据安全。详细配置和维护安全凭据请参考 User Management。
#连接端点参考
#集群内部访问
对于部署在同一 Kubernetes 集群内的应用,可通过 Access Method 标签页中 Access within the Cluster 部分获取内部访问端点。
| 参数 | 说明 |
|---|---|
| Connection Address | Redis Cluster 中每个分片对应的 Kubernetes 服务名和端口组合 |
#集群外部访问
对于集群外部连接的应用,若实例创建时配置了外部访问端点,可在 Access Method 标签页中 Access from outside the Cluster 部分查看。
| 端点类型 | 说明 |
|---|---|
| Shard Address | Redis Cluster 中分片 Pod 的外部 IP 和端口,支持 Kubernetes 网络外部的连接 |
#交互式调试
对于管理操作和故障排查,Redis CLI 提供了直接访问集群节点的方式:
-
在实例详情页打开 Terminal Console
-
使用集群感知客户端模式连接任意节点:
redis-cli -c -h <internal-routing-ip> -p 6379
示例调试会话,展示基于槽的重定向:
192.168.0.10:6379> set a 1
-> Redirected to slot [15495] located at 192.168.0.10:6379
OK
192.168.0.10:6379> get a
"1"
192.168.0.10:6379>-c 参数启用自动跟随 MOVED 和 ASK 重定向,使用 Redis Cluster 时必不可少。
#客户端集成示例
以下示例展示了使用不同客户端库连接 Redis Cluster 实例的最佳实践。
go-redis
Jedis
Lettuce
Redisson
package main
import (
"context"
"fmt"
"time"
// 建议定期升级客户端至最新版本以获得最新的 bug 修复。
"github.com/redis/go-redis/v9"
)
func main() {
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"<address>"},
Password: "<password>",
OnConnect: func(ctx context.Context, conn *redis.Conn) error {
ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
defer cancel()
return conn.Ping(ctx).Err()
},
// 用于追踪的客户端名称
ClientName: "go-demo",
// 启用 Context 进行超时控制
ContextTimeoutEnabled: true,
// MOVED 或 ASK 重定向的最大次数
MaxRedirects: 3,
// 最大重试次数
MaxRetries: 3,
// 最小重试间隔
MinRetryBackoff: 20 * time.Millisecond,
// 最大重试间隔
MaxRetryBackoff: 200 * time.Millisecond,
// 连接超时
DialTimeout: 3 * time.Second,
// 读取超时
ReadTimeout: 5 * time.Second,
// 写入超时
WriteTimeout: 10 * time.Second,
// 每个节点的连接池大小
PoolSize: 100,
// 连接池中等待可用连接的最大时间
PoolTimeout: time.Second,
// 每个节点的最小空闲连接数
MinIdleConns: 5,
// 每个节点的最大空闲连接数
MaxIdleConns: 10,
// 每个节点的最大活跃连接数
MaxActiveConns: 100,
// 连接最大空闲时间
ConnMaxIdleTime: time.Minute * 5,
})
defer client.Close()
if val, err := client.Get(context.TODO(), "test").Result(); err != nil {
panic(err)
} else {
fmt.Println(val)
}
}更多详细配置请参考 Community Documentation
package io.alauda.demo.redis;
// 建议定期升级客户端至最新版本以获得最新的 bug 修复。
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.HostAndPort;
import java.time.Duration;
import java.util.Set;
import java.util.HashSet;
public class Main {
public static void main(String []args) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 设置连接池大小,-1 表示不限制。当前连接数超过该值时,新连接将失败。
poolConfig.setMaxTotal(200);
// 设置最大空闲连接数,超过该数的空闲连接将被立即释放。
poolConfig.setMaxIdle(10);
// 设置最小空闲连接数,低于该数的空闲连接将被创建。
poolConfig.setMinIdle(3);
// 当无可用连接且达到最大连接数时的最大等待时间。
poolConfig.setMaxWait(Duration.ofSeconds(1));
// 每次从连接池借出连接时,使用 PING 验证连接是否可用。
poolConfig.setTestOnBorrow(true);
// 测试空闲连接以发现无效连接并释放,仅当 timeBetweenEvictionRunsMillis 大于 1ms 时生效。
poolConfig.setTestWhileIdle(true);
// 连接最小空闲时间,超过该时间的连接将被释放,-1 表示不释放,仅当 timeBetweenEvictionRunsMillis 大于 0 时生效,默认 30 分钟。
poolConfig.setMinEvictableIdleDuration(Duration.ofMinutes(5));
// 每次检测空闲连接时验证的连接数,-n 表示 1/n 的连接数。
poolConfig.setNumTestsPerEvictionRun(-1);
// 空闲连接检测间隔,-1 表示禁用。
poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
DefaultJedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
// 调试时用于检查连接来源的客户端名称。
.clientName("demo-jedis")
// TCP 连接超时。
.connectionTimeoutMillis(2000)
// 命令超时。
.timeoutMillis(10000)
.password("<password>")
.build();
DefaultJedisClientConfig sentinelConfig = DefaultJedisClientConfig.builder()
.connectionTimeoutMillis(2000)
.timeoutMillis(10000)
.build();
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("<ip1>", "<port1>"));
nodes.add(new HostAndPort("<ip2>", "<port2>"));
JedisSentinelPool pool = new JedisSentinelPool("mymaster", nodes, poolConfig, clientConfig, sentinelConfig);
try {
try (Jedis jedis = pool.getResource()) {
String val = jedis.get("test");
System.out.printf("%s", val);
}
} catch (Exception e) {
e.printStackTrace();
}
pool.close();
}
}更多详细配置请参考 Community Documentation
package io.alauda.demo.redis;
// 建议定期升级客户端至最新版本以获得最新的 bug 修复。
import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisURI;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.TimeoutOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.support.ConnectionPoolSupport;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import java.time.Duration;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
RedisURI node1 = RedisURI.create("<ip1>", "<port1>");
node1.setPassword("<password>");
node1.setClientName("demo-lettuce");
RedisURI node2 = RedisURI.create("<ip2>", "<port2>");
node2.setPassword("<password>");
node2.setClientName("demo-lettuce");
List<RedisURI> nodes = new ArrayList<>();
nodes.add(node1);
nodes.add(node2);
ClusterTopologyRefreshOptions refreshOptions = ClusterTopologyRefreshOptions.builder()
// 默认拓扑刷新间隔为 60 秒。
.enablePeriodicRefresh()
// 遇到以下错误时触发拓扑刷新:ASK_REDIRECT、MOVED_REDIRECT、PERSISTENT_RECONNECTS、UNCOVERED_SLOT、UNKNOWN_NODE
.enableAllAdaptiveRefreshTriggers()
.build();
TimeoutOptions timeoutOptions = TimeoutOptions.builder()
// 设置命令超时。
.fixedTimeout(Duration.ofSeconds(10))
.build();
SocketOptions socketOptions = SocketOptions.builder()
// 设置连接超时。
.connectTimeout(Duration.ofSeconds(10))
.tcpNoDelay(true)
// 启用 TCP keepalive 以快速识别无效连接。
// 非 pub/sub 请求此值非必需,可通过及时释放空闲连接管理。
.keepAlive(true)
.build();
ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
.topologyRefreshOptions(refreshOptions)
// 设置命令超时。
.timeoutOptions(timeoutOptions)
// 自动重连(默认行为)。
.autoReconnect(true)
// 配置断开连接时客户端行为。
// DEFAULT - 当 autoReconnect = true 时,命令不会被拒绝;否则命令会被拒绝。
.disconnectedBehavior(ClientOptions.DisconnectedBehavior.DEFAULT)
// 配置 socket 参数;lettuce 默认不启用 keepalive,长连接业务需启用。
.socketOptions(socketOptions)
.build();
RedisClusterClient redisClient = RedisClusterClient.create(nodes);
redisClient.setOptions(clusterClientOptions);
GenericObjectPoolConfig<StatefulRedisClusterConnection<String, String>> poolConfig = new GenericObjectPoolConfig<>();
// 连接池大小不宜过大,避免浪费服务器连接资源,导致连接耗尽和实例不可用。
// 建议根据业务并发除以分片数估算,最终值为 1.2-1.5 倍。
poolConfig.setMaxTotal(200);
// 保留最小空闲连接数以加快业务响应。
poolConfig.setMinIdle(3);
// 最大空闲连接数,超过该值立即释放空闲连接。
poolConfig.setMaxIdle(10);
// 连接最小空闲时间。
poolConfig.setMinEvictableIdleDuration(Duration.ofMinutes(5));
// 每次空闲连接检测时验证的连接数,-n 表示 1/n 的连接数。
poolConfig.setNumTestsPerEvictionRun(3);
// 空闲连接检测间隔,-1 表示禁用。
poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
// 当无可用连接且达到最大连接数时的最大等待时间。
poolConfig.setMaxWait(Duration.ofSeconds(1));
// 每次借出连接时使用 PING 验证连接可用性。
poolConfig.setTestOnBorrow(true);
// 测试空闲连接以发现无效连接并释放,仅当 timeBetweenEvictionRunsMillis 大于 1ms 时生效。
poolConfig.setTestWhileIdle(true);
GenericObjectPool<StatefulRedisClusterConnection<String, String>> pool = ConnectionPoolSupport
.createGenericObjectPool(redisClient::connect, poolConfig);
try {
try (StatefulRedisClusterConnection<String, String> connection = pool.borrowObject()) {
String val = connection.sync().get("test");
System.out.printf("%s", val);
}
} catch (Exception e) {
e.printStackTrace();
}
pool.close();
}
}更多详细配置请参考 Community Documentation
package io.alauda.demo.redis;
// 建议定期升级客户端至最新版本以获得最新的 bug 修复。
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
List<String> nodes = new ArrayList<>();
nodes.add("redis://<ip1>:<port1>");
nodes.add("redis://<ip2>:<port2>");
Config config = new Config();
config
.setNettyThreads(64)
.useClusterServers()
.addNodeAddress(nodes.toArray(new String[0]))
.setPassword("<password>")
// 启动服务时检查集群槽状态。
.setCheckSlotsCoverage(true)
// 扫描集群拓扑的间隔。
.setScanInterval(5000)
// 连接超时。
.setConnectTimeout(10000)
// 命令超时。
.setTimeout(10000)
// 每 30 秒测试一次连接可用性。
// 若启用 KeepAlive,此超时可按比例延长。
.setPingConnectionInterval(30000)
// 空闲连接超时,丢弃空闲超过 60 秒的连接,默认 10 秒过短。
.setIdleConnectionTimeout(60000)
// 连接池大小不宜过大,避免浪费服务器连接资源,导致连接耗尽和实例不可用。
// 建议根据业务并发除以分片数估算,最终值为 1.2-1.5 倍。
.setMasterConnectionPoolSize(200)
// 保留最小空闲连接数以加快业务响应。
.setMasterConnectionMinimumIdleSize(10)
// 失败命令的重试次数。
.setRetryAttempts(3)
// 失败命令的重试间隔。
.setRetryInterval(1500)
// 启用 TCP keepalive 机制,快速发现异常断开的连接。
.setKeepAlive(true)
// TCP no delay。
.setTcpNoDelay(true)
// 调试时用于检查连接来源的客户端名称。
.setClientName("demo-redisson");
RedissonClient redissonClient = Redisson.create(config);
System.out.printf("%s", redissonClient.getBucket("test").get().toString());
redissonClient.shutdown();
}
}更多详细配置请参考 Community Documentation