#如何访问哨兵实例
本指南展示了如何使用行业标准的客户端库连接 Redis 哨兵实例。示例包括 go-redis、Jedis、Lettuce 和 Redisson 的配置细节。有关其他客户端选项,请参见 Redis 客户端兼容矩阵。
#目录
#认证要求
Redis 哨兵实例实现以下认证选项:
- 密码认证:当配置了密码时,所有客户端连接必须提供有效的凭证。
- 无密码访问:如果在实例创建时禁用了 设置密码 选项,客户端可以无认证连接。
安全最佳实践
在生产环境中,强烈建议实现密码认证以保护您的数据。有关配置和维护安全凭证的详细说明,请参见 用户管理。
#连接端点参考
#内部集群访问
对于部署在相同 Kubernetes 集群的应用程序,可以通过 访问方式 页签下的 集群内访问 部分获取内部访问端点。
| 参数 | 说明 |
|---|---|
| 连接地址 | Kubernetes 服务名称与 Redis 哨兵的端口组合。 |
#外部集群访问
如果在创建实例时启用了 外部访问 方法,客户端可以通过实例 访问方式 页签下的 外部访问 部分的地址连接到 Redis。
| 参数 | 说明 |
|---|---|
| 哨兵节点访问地址 | Redis 哨兵中 Pods 的外部 IP 地址和端口,允许从 Kubernetes 网络外部进行连接。 |
#交互式调试
在实例详细信息页面,单击右上角的 终端控制台,并使用 redis-cli 命令连接每个 Redis 节点。
redis-cli -h <内部路由 IP> -p 6379下面是一个调试示例。演示 set/get 的调试会话:
192.168.0.10:6379> set a 1
OK
192.168.0.10:6379> get a
"1"
192.168.0.10:6379>#客户端集成示例
以下示例展示了如何使用各种客户端库连接 Redis 哨兵实例的最佳实践。
注意:哨兵模式中注册的主从集群名称固定为
mymaster。
go-redis
Jedis
Lettuce
Redisson
package main
import (
"context"
"fmt"
"time"
// 建议定期升级到客户端的最新版本,以获得最新的 bug 修复。
"github.com/redis/go-redis/v9"
)
func main() {
client := redis.NewFailoverClient(&redis.FailoverOptions{
SentinelAddrs: []string{"<address>"},
MasterName: "mymaster",
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,
// 最大重试次数
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)
}
}更多详细配置请参考 社区文档。
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 时才会生效。默认值 30m
poolConfig.setMinEvictableIdleDuration(Duration.ofMinutes(5));
// 每次检测空闲连接时执行验证的连接数,-n 表示 1/n 个连接
poolConfig.setNumTestsPerEvictionRun(-1);
// 驱逐时间的间隔,-1 表示禁用
poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
DefaultJedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
// 客户端名称,用于 debug 时,查看连接来源
.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();
}
}更多详细配置请参考 社区文档。
package io.alauda.demo.redis;
// 建议定期升级到客户端的最新版本,以获得最新的 bug 修复。
import io.lettuce.core.*;
import io.lettuce.core.api.StatefulRedisConnection;
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;
public class Main {
public static void main(String[] args) {
RedisURI.Builder redisUriBuilder = RedisURI.builder();
redisUriBuilder.withSentinel(RedisURI.create("<ip1>", "<port1>"));
redisUriBuilder.withSentinel(RedisURI.create("<ip2>", "<port2>"));
redisUriBuilder.withPassword("<password>");
// 客户端名称,用于 debug 时,查看连接来源
redisUriBuilder.withClientName("demo-lettuce");
redisUriBuilder.withSentinelMasterId("mymaster");
// 设置客户端连接超时时间
redisUriBuilder.withTimeout(Duration.ofSeconds(2));
RedisURI redisUri = redisUriBuilder.build();
// 配置 SocketOptions
SocketOptions socketOptions = SocketOptions.builder()
// 设置连接超时时间
.connectTimeout(Duration.ofSeconds(10))
.tcpNoDelay(true)
// 开启 TCP keepalive,用于快速发现无效连接
// 该值在非 pub/sub 类型的请求上不是必须的;可通过 idle 连接的及时释放来实现连接的探活
.keepAlive(true)
.build();
ClientOptions clientOptions = ClientOptions.builder()
.socketOptions(socketOptions)
// 连接自动重连
.autoReconnect(true)
// 配置在连接断开时,客户端的行为。
// DEFAULT - 当 autoReconnect = true 时,命令将不会被拒绝;否则,命令将被拒绝
.disconnectedBehavior(ClientOptions.DisconnectedBehavior.DEFAULT)
.build();
RedisClient redisClient = RedisClient.create(redisUri);
redisClient.setOptions(clientOptions);
// 连接池配置
GenericObjectPoolConfig<StatefulRedisConnection<String, String>> poolConfig = new GenericObjectPoolConfig<>();
// 连接池大小,不可太大,不然会造成服务器连接资源的浪费,甚至造成连接数耗尽,导致实例自身的探活失败。
// 需要预估自己的业务并发,建议并发量为自己业务规模的 1.2-1.5 倍
poolConfig.setMaxTotal(200);
// 最小空闲连接数,预留部分空闲连接,加速业务响应
poolConfig.setMinIdle(3);
// 最大空闲连接数,超过这个范围的空闲连接会被立即释放
poolConfig.setMaxIdle(10);
// 设置连接的最小空闲时间,超过这个时间的连接会被释放;-1 表示不释放,该配置只有在 timeBetweenEvictionRunsMillis 大于 0 时才会生效。默认值 30m
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<StatefulRedisConnection<String, String>> pool = ConnectionPoolSupport.createGenericObjectPool(redisClient::connect, poolConfig);
try {
try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
String val = connection.sync().get("test");
System.out.printf("%s", val);
}
} catch (Exception e) {
e.printStackTrace();
}
pool.close();
}
}更多详细配置请参考 社区文档。
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)
.useSentinelServers()
.addSentinelAddress(nodes.toArray(new String[0]))
.setPassword("<password>")
.setMasterName("mymaster")
// 启用哨兵节点发现
.setSentinelsDiscovery(true)
// 每 30s 测试一次连接,用于检测连接可用性
// 如果开启了 KeepAlive,该值的时间可以相应变长
.setPingConnectionInterval(30000)
// 每次扫描集群拓扑的时间间隔
.setScanInterval(2000)
// 连接超时时间
.setConnectTimeout(10000)
// 命令超时时间
.setTimeout(10000)
// 空闲连接超时时间,设置为 60s 以避免默认值过短
.setIdleConnectionTimeout(60000)
// 连接池大小,不可太大,否则会浪费服务器连接资源,甚至耗尽连接数,导致实例自身的探活失败。
// 需要预估自己的业务并发,建议并发量为自己业务规模的 1.2-1.5 倍
.setMasterConnectionPoolSize(200)
// 最小空闲连接数,预留部分空闲连接,加速业务响应
.setMasterConnectionMinimumIdleSize(3)
// 失败命令重试次数
.setRetryAttempts(3)
// 失败命令重试时间间隔
.setRetryInterval(1500)
// 启用 TCP KeepAlive 机制,用于快速发现意外断开的连接
.setKeepAlive(true)
// 启用 TCP 无延迟
.setTcpNoDelay(true)
// 客户端名称,用于 debug 时,查看连接来源
.setClientName("demo-redisson");
RedissonClient redissonClient = Redisson.create(config);
System.out.printf("%s", redissonClient.getBucket("test").get().toString());
redissonClient.shutdown();
}
}更多详细配置请参考 社区文档。