#Как получить доступ к экземпляру кластера
В этом руководстве показано, как устанавливать соединения с экземплярами 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 | Имя сервиса Kubernetes и комбинации портов для каждого шарда в Redis Cluster |
#Внешний доступ к кластеру
Для приложений, подключающихся извне Kubernetes, доступны внешние конечные точки, если они были настроены при создании экземпляра. Эти конечные точки можно найти во вкладке Access Method в разделе Access from outside the Cluster.
| Тип конечной точки | Описание |
|---|---|
| Shard Address | Внешние IP-адреса и порты для подов шарда в Redis Cluster, обеспечивающие подключение из внешней сети 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 с использованием различных клиентских библиотек.
package main
import (
"context"
"fmt"
"time"
// Рекомендуется периодически обновлять клиент до последней версии для получения последних исправлений ошибок.
"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;
import redis.clients.jedis.ConnectionPoolConfig;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.JedisCluster;
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) {
// Настройка параметров пула Jedis
ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();
// Установка размера пула соединений; -1 означает неограниченно. Новые соединения будут отклонены при превышении лимита.
poolConfig.setMaxTotal(200);
// Установка максимального количества неактивных соединений; неактивные соединения сверх этого лимита будут немедленно освобождены.
poolConfig.setMaxIdle(10);
// Установка минимального количества неактивных соединений; новые неактивные соединения будут создаваться при снижении ниже этого порога.
poolConfig.setMinIdle(3);
// Максимальное время ожидания при отсутствии доступных соединений и достижении максимального количества соединений.
poolConfig.setMaxWait(Duration.ofSeconds(1));
// PING для проверки доступности соединения при каждом взятии соединения из пула.
poolConfig.setTestOnBorrow(true);
// Тестирование неактивных соединений для обнаружения и освобождения недействительных; эффективно только при timeBetweenEvictionRunsMillis > 1мс.
poolConfig.setTestWhileIdle(true);
// Минимальное время бездействия для соединений; соединения, превышающие это время, будут освобождены. -1 означает никогда не освобождать. Эффективно при timeBetweenEvictionRunsMillis > 0. По умолчанию: 30м.
poolConfig.setMinEvictableIdleDuration(Duration.ofMinutes(5));
// Количество соединений для проверки при каждом запуске проверки неактивных соединений; -n означает 1/n соединений.
poolConfig.setNumTestsPerEvictionRun(-1);
// Интервал проверки неактивных соединений; отрицательное значение означает отсутствие потока очистки.
poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(1));
// Максимальное количество попыток повторного подключения.
int maxAttempts = 3;
// Максимальная длительность попыток повторного подключения.
Duration maxAttemptsDuration = Duration.ofSeconds(3);
// Интервал обновления топологии.
Duration topologyRefreshPeriod = Duration.ofMinutes(1);
JedisClientConfig clientConfig = DefaultJedisClientConfig.builder()
// Таймаут подключения, по умолчанию 2 секунды.
.connectionTimeoutMillis(2000)
// Таймаут команд.
.timeoutMillis(10000)
// Имя клиента для идентификации источника соединения при отладке.
.clientName("demo-jedis")
.password("<password>")
.build();
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("<ip1>", <port1>));
nodes.add(new HostAndPort("<ip2>", <port2>));
JedisCluster cluster = new JedisCluster(nodes, clientConfig, poolConfig, topologyRefreshPeriod, maxAttempts, maxAttemptsDuration);
try {
String val = cluster.get("test");
System.out.printf("%s", val);
} catch (Exception e) {
e.printStackTrace();
}
cluster.close();
}
}Для более подробной конфигурации смотрите Community Documentation
package io.alauda.demo.redis;
// Рекомендуется периодически обновлять клиент до последней версии для получения последних исправлений ошибок.
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)
// Настройка параметров сокета; 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 > 1мс.
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;
// Рекомендуется периодически обновлять клиент до последней версии для получения последних исправлений ошибок.
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 без задержек.
.setTcpNoDelay(true)
// Имя клиента для проверки источника соединения при отладке.
.setClientName("demo-redisson");
RedissonClient redissonClient = Redisson.create(config);
System.out.printf("%s", redissonClient.getBucket("test").get().toString());
redissonClient.shutdown();
}
}Для более подробной конфигурации смотрите Community Documentation