#Как получить доступ к экземпляру кластера
В этом руководстве показано, как устанавливать соединения с экземплярами 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 |
#Интерактивная отладка
Для административных операций и устранения неполадок CLI Redis предоставляет прямой доступ к узлам кластера:
-
Откройте 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 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