Tous les produits
Search
Centre de documentation

Tair (Redis® OSS-Compatible):Utiliser le mode de connexion directe pour se connecter à une instance en cluster

Dernière mise à jour :Aug 08, 2026

Le mode de connexion directe permet à un client de se connecter aux serveurs de données d'une instance en cluster Tair (compatible avec Redis OSS) via le protocole natif Redis Cluster. Cette approche contourne la couche proxy, réduit la latence des réponses et facilite la migration depuis des déploiements Redis Cluster auto-gérés.

Mode de connexion directe vs mode proxy

Aspect Mode de connexion directe Mode proxy
Latence Plus faible (aucun saut via le proxy) Légèrement plus élevée
Prérequis client Doit prendre en charge le protocole Redis Cluster Tout client Redis
Mise à l'échelle Le client gère la conscience de la topologie Transparent pour le client
Haute disponibilité Le client gère les redirections Le proxy gère le basculement

Pour plus d'informations sur le mode proxy, consultez Features of proxy nodes.

Fonctionnement

Lorsque le mode de connexion directe est activé, Tair (compatible avec Redis OSS) attribue une adresse IP virtuelle (VIP) au nœud maître de chaque shard de données. Un serveur DNS résout le point de terminaison privé vers la VIP d'un shard de données aléatoire. Le client utilise ensuite cette VIP pour gérer les données de l'instance selon le protocole Redis Cluster.

image

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Une instance en cluster Tair (compatible avec Redis OSS) avec le mode de connexion directe activé. Pour plus d'informations, consultez Activer le mode de connexion directe

  • Ajouté l'adresse IP du client à une liste d'autorisation. Pour plus d'informations, consultez Configurer les listes d'autorisation

  • Une instance Elastic Compute Service (ECS) située dans le même Virtual Private Cloud (VPC) que l'instance en cluster

Bibliothèques clientes prises en charge

Les bibliothèques clientes suivantes prennent en charge le protocole Redis Cluster et fonctionnent avec le mode de connexion directe.

Client Langage Version testée GitHub Notes
Jedis Java 4.3.0 jedis Recommandé pour Spring Data Redis
Lettuce Java 6.3.0.RELEASE ou ultérieure lettuce-core Nécessite un réglage de TCP keepalive. Consultez Référence des paramètres Lettuce
redis-py Python 4.4.1 redis-py Utilisez la classe RedisCluster
PhpRedis PHP 5.3.7 phpredis -
StackExchange.Redis .NET 2.6.90 - Ne prend pas en charge SELECT (DB0 uniquement)
node-redis Node.js 4.5.1 - Fournissez les identifiants dans rootNodes et defaults
go-redis Go 9.5.1 (9,0 ou ultérieure requise) - Les versions antérieures à 9,0 provoquent des erreurs d'incompatibilité
Si un client ne prend pas en charge le protocole Redis Cluster, il ne peut pas rediriger les requêtes vers le shard approprié. Cela peut entraîner des échecs de récupération des données. Pour obtenir la liste complète des clients compatibles, consultez la page Clients sur le site web de Redis.

Notes d'utilisation

Se connecter avec redis-cli

Incluez le paramètre -c pour activer le mode cluster lors de la connexion via un point de terminaison privé. Sans ce paramètre, la connexion échoue.

./redis-cli -h r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com -p 6379 -c

Authentifiez-vous avec votre compte de base de données :

AUTH testaccount:Rp829dlwa

Pour plus d'informations, consultez Utiliser redis-cli pour se connecter à une instance.

Se connecter avec Jedis

Les exemples suivants utilisent Jedis 4.3.0. Pour plus d'informations, visitez GitHub.

Pool de connexions personnalisé (recommandé)

Un pool de connexions personnalisé offre un contrôle sur les limites de connexion. En mode de connexion directe, chaque client se connecte directement aux shards individuels. Définissez les tailles de pool de sorte que le nombre total de connexions entre tous les clients ne dépasse pas le nombre maximal de connexions par shard : Nombre de clients x MaxTotal < Nombre maximal de connexions vers un seul shard.

Paramètre Valeur Description
MaxTotal 30 Nombre maximal de connexions dans le pool. Doit satisfaire la formule par shard ci-dessus.
MaxIdle 20 Nombre maximal de connexions inactives. Définissez en fonction de la charge de travail.
MinIdle 15 Nombre minimal de connexions inactives à maintenir.
import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;

public class DirectTest {
    private static final int DEFAULT_TIMEOUT = 2000;
    private static final int DEFAULT_REDIRECTIONS = 5;
    private static final ConnectionPoolConfig config = new ConnectionPoolConfig();

    public static void main(String args[]) {
        // Number of clients x MaxTotal < Maximum connections to a single shard.
        config.setMaxTotal(30);
        config.setMaxIdle(20);
        config.setMinIdle(15);

        // Private endpoint of the cluster instance.
        String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com";
        int port = 6379;
        // Password for the cluster instance.
        String password = "xxxxx";

        Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort(host, port));
        JedisCluster jc = new JedisCluster(jedisClusterNode, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT, DEFAULT_REDIRECTIONS,
            password, "clientName", config);

        jc.set("key", "value");
        jc.get("key");

        jc.close();     // Close the connection and release resources when the application exits.
    }
}

Pool de connexions par défaut

import redis.clients.jedis.ConnectionPoolConfig;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.HashSet;
import java.util.Set;

public class DirectTest{
    private static final int DEFAULT_TIMEOUT = 2000;
    private static final int DEFAULT_REDIRECTIONS = 5;
    private static final ConnectionPoolConfig DEFAULT_CONFIG = new ConnectionPoolConfig();

    public static void main(String args[]){

        // Private endpoint of the cluster instance.
        String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com";
        int port = 6379;
        String password = "xxxx";

        Set<HostAndPort>  jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort(host, port));

        JedisCluster jc = new JedisCluster(jedisClusterNode, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
            DEFAULT_REDIRECTIONS,password, "clientName", DEFAULT_CONFIG);

        jc.set("key","value");
        jc.get("key");

        jc.close();     // Close the connection and release resources when the application exits.
    }
}

Se connecter avec PhpRedis

L'exemple suivant utilise PhpRedis 5.3.7. Pour plus d'informations, visitez GitHub.

<?php
 // Private endpoint and port of the cluster instance.
 $array = ['r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379'];
 // Password for the cluster instance.
 $pwd = "xxxx";

 // Connect to the cluster instance with the password.
 $obj_cluster = new RedisCluster(NULL, $array, 1.5, 1.5, true, $pwd);

 // Display the connection result.
 var_dump($obj_cluster);

 if ($obj_cluster->set("foo", "bar") == false) {
     die($obj_cluster->getLastError());
 }
 $value = $obj_cluster->get("foo");
 echo $value;
 ?>

Se connecter avec redis-py

L'exemple suivant utilise Python 3.9 et redis-py 4.4.1. Pour plus d'informations, visitez GitHub.

# !/usr/bin/env python
# -*- coding: utf-8 -*-
from redis.cluster import RedisCluster
# Replace with the endpoint and port of the instance.
host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com'
port = 6379
# Replace with the username and password of the instance.
user = 'testaccount'
pwd = 'Rp829dlwa'
rc = RedisCluster(host=host, port=port, username=user, password=pwd)
# Perform operations after connecting. Example: set and get.
rc.set('foo', 'bar')
print(rc.get('foo'))

Se connecter avec Spring Data Redis

Le projet Maven suivant utilise Spring Data Redis 2.4.2. Vous pouvez également télécharger manuellement le client Lettuce ou Jedis.

Étape 1 : Ajouter les dépendances Maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aliyun.tair</groupId>
    <artifactId>spring-boot-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-example</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.3.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-transport-native-epoll</artifactId>
            <version>4.1.100.Final</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Étape 2 : Configurer la connexion

Choisissez Jedis (recommandé) ou Lettuce comme client sous-jacent.

Spring Data Redis avec Jedis (recommandé)

@Bean
    JedisConnectionFactory redisConnectionFactory() {
        List<String> clusterNodes = Arrays.asList("r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379");
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(clusterNodes);
        redisClusterConfiguration.setUsername("user");
        redisClusterConfiguration.setPassword("password");

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // Number of clients x MaxTotal < Maximum connections to a single shard.
        jedisPoolConfig.setMaxTotal(30);
        jedisPoolConfig.setMaxIdle(20);
        // Disable testOn[Borrow|Return] to avoid extra ping commands.
        jedisPoolConfig.setTestOnBorrow(false);
        jedisPoolConfig.setTestOnReturn(false);

        return new JedisConnectionFactory(redisClusterConfiguration, jedisPoolConfig);
    }

Spring Data Redis avec Lettuce

Avertissement
/**
     * Enable TCP keepalive and configure the following three parameters:
     *  TCP_KEEPIDLE = 30
     *  TCP_KEEPINTVL = 10
     *  TCP_KEEPCNT = 3
     */
    private static final int TCP_KEEPALIVE_IDLE = 30;

    /**
     * TCP_USER_TIMEOUT avoids scenarios where Lettuce remains stuck in a
     * continuous timeout loop during a failure or crash event.
     * refer: https://github.com/lettuce-io/lettuce-core/issues/2082
     */
    private static final int TCP_USER_TIMEOUT = 30;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        List<String> clusterNodes = Arrays.asList("r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379");
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(clusterNodes);
        redisClusterConfiguration.setUsername("user");
        redisClusterConfiguration.setPassword("password");

        // Config TCP KeepAlive
        SocketOptions socketOptions = SocketOptions.builder()
            .keepAlive(KeepAliveOptions.builder()
                .enable()
                .idle(Duration.ofSeconds(TCP_KEEPALIVE_IDLE))
                .interval(Duration.ofSeconds(TCP_KEEPALIVE_IDLE / 3))
                .count(3)
                .build())
            .tcpUserTimeout(TcpUserTimeoutOptions.builder()
                .enable()
                .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT))
                .build())
            .build();

        ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
            .enablePeriodicRefresh(Duration.ofSeconds(60))
            .dynamicRefreshSources(false)
            .enableAllAdaptiveRefreshTriggers()
            .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(15)).build();

        LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder().
            clientOptions(ClusterClientOptions.builder()
                .socketOptions(socketOptions)
                .validateClusterNodeMembership(false)
                .topologyRefreshOptions(topologyRefreshOptions).build()).build();

        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }

Se connecter avec .NET (StackExchange.Redis)

L'exemple suivant utilise .NET 6.0 et StackExchange.Redis 2.6.90.

using StackExchange.Redis;

class RedisConnSingleton {
    // Endpoint, port, username, and password for the cluster instance.
    private static ConfigurationOptions configurationOptions = ConfigurationOptions.Parse("r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379,user=testaccount,password=Rp829dlwa,connectTimeout=2000");
    //the lock for singleton
    private static readonly object Locker = new object();
    //singleton
    private static ConnectionMultiplexer redisConn;
    //singleton
    public static ConnectionMultiplexer getRedisConn()
    {
        if (redisConn == null)
        {
            lock (Locker)
            {
                if (redisConn == null || !redisConn.IsConnected)
                {
                    redisConn = ConnectionMultiplexer.Connect(configurationOptions);
                }
            }
        }
        return redisConn;
    }
}

class Program
{
    static void Main(string[] args)
    {
        ConnectionMultiplexer cm = RedisConnSingleton.getRedisConn();
        var db = cm.GetDatabase();
        db.StringSet("key", "value");
        String ret = db.StringGet("key");
        Console.WriteLine("get key: " + ret);
    }
}

Se connecter avec node-redis

L'exemple suivant utilise Node.js 19.4.0 et node-redis 4.5.1.

Fournissez les identifiants à la fois dans l'URL rootNodes et dans l'objet defaults. Les identifiants defaults authentifient les connexions vers tous les autres nœuds du cluster. Sans eux, une erreur NOAUTH se produit.

import { createCluster } from 'redis';

// Endpoint, port, username, and password for the instance.
// After supplying the username and password in the url parameter,
// also supply them in the defaults parameter.
// The defaults credentials authenticate the remaining nodes.
// Without defaults, a NOAUTH error occurs.

const cluster = createCluster({
    rootNodes: [{
        url: 'redis://testaccount:Rp829dlwa@r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379'
    }],
    defaults: {
        username: 'testaccount',
        password: 'Rp829dlwa'
    }
});

cluster.on('error', (err) => console.log('Redis Cluster Error', err));

await cluster.connect();

await cluster.set('key', 'value');
const value = await cluster.get('key');
console.log('get key: %s', value);

await cluster.disconnect();

Se connecter avec go-redis

L'exemple suivant utilise Go 1.19.7 et go-redis 9.5.1.

Important

Utilisez go-redis 9,0 ou une version ultérieure. Les versions antérieures peuvent provoquer des erreurs d'incompatibilité lors de la connexion via un point de terminaison privé. Pour plus d'informations, consultez Erreurs courantes et dépannage.

package main

import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v9"
)

var ctx = context.Background()

func main() {
	rdb := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs:    []string{"r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379"},
		Username: "testaccount",
		Password: "Rp829dlwa",
	})

	err := rdb.Set(ctx, "key", "value", 0).Err()
	if err != nil {
		panic(err)
	}

	val, err := rdb.Get(ctx, "key").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println("key", val)
}

Se connecter avec Lettuce (autonome)

Avertissement

Étape 1 : Ajouter les dépendances Maven

<dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.3.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-transport-native-epoll</artifactId>
            <version>4.1.65.Final</version>
            <classifier>linux-x86_64</classifier>
        </dependency>

Étape 2 : Ajouter le code de connexion

Remplacez les valeurs de host, port et password par les informations réelles de l'instance.

import io.lettuce.core.RedisURI;
import io.lettuce.core.SocketOptions;
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 java.time.Duration;

public class ClusterDemo {
    /**
     * Enable TCP keepalive and configure the following three parameters:
     *  TCP_KEEPIDLE = 30
     *  TCP_KEEPINTVL = 10
     *  TCP_KEEPCNT = 3
     */
    private static final int TCP_KEEPALIVE_IDLE = 30;

    /**
     * TCP_USER_TIMEOUT avoids situations where Lettuce remains stuck in a
     * continuous timeout loop during a failure or crash event.
     * refer: https://github.com/lettuce-io/lettuce-core/issues/2082
     */
    private static final int TCP_USER_TIMEOUT = 30;

    public static void main(String[] args) throws Exception {
        // Replace with the actual instance information.
        String host = "r-bp1ln3c4kopj3l****.redis.rds.aliyuncs.com";
        int port = 6379;
        String password = "Da****3";

        RedisURI redisURI = RedisURI.Builder.redis(host)
                .withPort(port)
                .withPassword(password)
                .build();

        ClusterTopologyRefreshOptions refreshOptions = ClusterTopologyRefreshOptions.builder()
                .enablePeriodicRefresh(Duration.ofSeconds(60))
                .dynamicRefreshSources(false)
                .enableAllAdaptiveRefreshTriggers()
                .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(15)).build();

        // Config TCP KeepAlive
        SocketOptions socketOptions = SocketOptions.builder()
                .keepAlive(SocketOptions.KeepAliveOptions.builder()
                        .enable()
                        .idle(Duration.ofSeconds(TCP_KEEPALIVE_IDLE))
                        .interval(Duration.ofSeconds(TCP_KEEPALIVE_IDLE/3))
                        .count(3)
                        .build())
                .tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()
                        .enable()
                        .tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT))
                        .build())
                .build();

        RedisClusterClient redisClient = RedisClusterClient.create(redisURI);
        redisClient.setOptions(ClusterClientOptions.builder()
                .socketOptions(socketOptions)
                .validateClusterNodeMembership(false)
                .topologyRefreshOptions(refreshOptions).build());

        StatefulRedisClusterConnection<String, String> connection = redisClient.connect();
        connection.sync().set("key", "value");
        System.out.println(connection.sync().get("key"));
    }
}

Sortie attendue en cas de succès :

value

Référence des paramètres Lettuce

Les paramètres suivants contrôlent l'actualisation de la topologie du cluster Lettuce et le comportement TCP. Des valeurs par défaut incorrectes peuvent entraîner une augmentation de la latence et une indisponibilité lors des modifications de l'instance.

Paramètre Par défaut Recommandé Description
enablePeriodicRefresh(Duration) Désactivé 60 secondes Active l'actualisation périodique de la topologie du cluster. Maintient la vue locale de la topologie à jour, même pour les connexions persistantes inactives.
dynamicRefreshSources(boolean) true false Lorsque true, tous les nœuds renvoyés par CLUSTER NODES actualisent la topologie, ce qui augmente la charge du serveur. Lorsque false, seul le point de terminaison spécifié est utilisé. Lors des modifications de configuration, le point de terminaison est généralement plus rapide et plus fiable.
enableAllAdaptiveRefreshTriggers() Désactivé Activé (requis) Déclenche une actualisation automatique de la topologie lorsqu'un message MOVED est reçu. Sans cela, Lettuce ne peut pas mettre à jour la topologie locale après un changement de topologie.
adaptiveRefreshTriggersTimeout(Duration) 30 s 15 s Limite la fréquence d'actualisation de la topologie à une actualisation par période de délai d'attente. Les changements de topologie entre les nœuds ne sont pas atomiques, donc la première actualisation peut échouer. Un délai d'attente plus court permet une actualisation de suivi plus rapide. Réduisez encore cette valeur lorsque le nombre d'applications clientes est faible.
validateClusterNodeMembership(boolean) true false (requis) Lorsque true, les redirections MOVED vont uniquement vers les nœuds listés dans la sortie CLUSTER NODES. Définissez sur false pour permettre l'accès aux nœuds nouvellement ajoutés avant que la topologie locale ne soit actualisée.

FAQ

Pourquoi l'erreur MOVED 4578 172.18.xx.xxx:6379 se produit-elle ?

L'erreur MOVED <slot> <IP:Port> signifie que la clé demandée se trouve sur un nœud différent. Cela se produit généralement lorsque le client ne prend pas en charge le protocole Redis Cluster. Les scénarios courants incluent :

  • Connexion avec redis-cli sans l'option -c.

  • Utilisation du client standard redis-py en Python, qui ne gère pas la redirection automatique. Utilisez plutôt la classe redis.cluster.RedisCluster.

Pour plus d'informations sur les autres erreurs, consultez Erreurs courantes et dépannage.