#Как получить доступ к экземпляру кластера
В этом руководстве показано, как устанавливать соединения с экземплярами 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.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 больше 1 мс.
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;
// Рекомендуется периодически обновлять клиент до последней версии для получения последних исправлений ошибок.
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