Tüm Ürünler
Search
Belge Merkezi

Tair (Redis® OSS-Compatible):Use direct connection mode to connect to a cluster instance

Son Güncelleme:Oct 03, 2026

Doğrudan bağlantı modu, bir istemciyi Tair (Redis OSS-Uyumlu) küme örneğinin veri sunucularına yerel Redis Cluster protokolü kullanarak bağlar. Bu yöntem proxy katmanını atlayarak yanıt gecikme süresini azaltır ve kendi kendinize yönetilen Redis Cluster dağıtımlarından sorunsuz geçiş imkanı sunar.

Doğrudan bağlantı ve proxy modu karşılaştırması

Yön Doğrudan bağlantı modu Proxy modu
Gecikme süresi Daha düşük (proxy atlama yok) Biraz daha yüksek
İstemci gereksinimi Redis Cluster protokolünü desteklemelidir Herhangi bir Redis istemcisi
Ölçeklenebilirlik İstemci topoloji farkındalığını yönetir İstemci için şeffaf
Yüksek kullanılabilirlik İstemci yeniden yönlendirmeleri işler Proxy yük devretmeyi işler

Proxy modu hakkında daha fazla bilgi için bkz. Features of proxy nodes.

Çalışma mantığı

Doğrudan bağlantı modu etkinleştirildiğinde Tair (Redis OSS-Uyumlu), her bir veri parçasının ana düğümüne bir sanal IP adresi (VIP) tahsis eder. Bir Alan Adı Sistemi (DNS) sunucusu özel uç noktayı rastgele bir veri parçasının VIP'sine çözümler. İstemci daha sonra bu VIP'yi kullanarak Redis Cluster protokolüne göre örnek verilerini yönetir.

image

Ön koşullar

Başlamadan önce aşağıdakileri yaptığınızdan emin olun:

  • Doğrudan bağlantı modu etkinleştirilmiş bir Tair (Redis OSS-Uyumlu) küme örneği. Daha fazla bilgi için bkz. Enable the direct connection mode

  • İstemci IP adresini bir izin listesine ekleyin. Daha fazla bilgi için bkz. Configure whitelists

  • Küme örneğiyle aynı Sanal Özel Bulut (VPC) içinde bulunan bir Elastic Compute Service (ECS) örneği

Desteklenen istemci kitaplıkları

Aşağıdaki istemci kitaplıkları Redis Cluster protokolünü destekler ve doğrudan bağlantı modu ile çalışır.

İstemci Dil Test edilen sürüm GitHub Notlar
Jedis Java 4.3.0 jedis Spring Data Redis için önerilir
Lettuce Java 6.3.0.RELEASE veya üzeri lettuce-core TCP keepalive ayarı gerekir. Bkz. Lettuce parametre referansı
redis-py Python 4.4.1 redis-py RedisCluster sınıfını kullanın
PhpRedis PHP 5.3.7 phpredis -
StackExchange.Redis .NET 2.6.90 - SELECT'i desteklemez (yalnızca DB0)
node-redis Node.js 4.5.1 - Kimlik bilgilerini hem rootNodes hem de defaults içinde sağlayın
go-redis Go 9.5.1 (9,0 veya üzeri gerekir) - 9,0'dan önceki sürümler uyumsuzluk hatalarına neden olur
Bir istemci Redis Cluster protokolünü desteklemiyorsa istekleri doğru parçaya yönlendiremez. Bu durum veri alma hatalarına yol açabilir. Uyumlu istemcilerin tam listesi için Redis web sitesindeki Clients sayfasına bakın.

Kullanım notları

redis-cli ile bağlanma

Özel bir uç nokta üzerinden bağlanırken küme modunu etkinleştirmek için -c parametresini ekleyin. Aksi takdirde bağlantı başarısız olur.

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

Veritabanı hesabınızla kimlik doğrulaması yapın:

AUTH testaccount:Rp829dlwa

Daha fazla bilgi için bkz. Use redis-cli to connect to an instance.

Jedis ile bağlanma

Aşağıdaki örneklerde Jedis 4.3.0 kullanılmaktadır. Daha fazla bilgi için GitHub adresini ziyaret edin.

Özel bağlantı havuzu (önerilir)

Özel bir bağlantı havuzu bağlantı sınırları üzerinde kontrol sağlar. Doğrudan bağlantı modunda her istemci doğrudan tek tek parçalara bağlanır. Tüm istemcilerdeki toplam bağlantı sayısının tek bir parça için maksimum bağlantı sayısını aşmaması için havuz boyutlarını ayarlayın: İstemci sayısı x MaxTotal < Tek bir parçaya maksimum bağlantı sayısı.

Parametre Değer Açıklama
MaxTotal 30 Havuzdaki maksimum bağlantı sayısı. Yukarıdaki parça başı formülü karşılamalıdır.
MaxIdle 20 Maksimum boşta kalan bağlantı sayısı. İş yüküne göre ayarlayın.
MinIdle 15 Korunacak minimum boşta kalan bağlantı sayısı.
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.
    }
}

Varsayılan bağlantı havuzu

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.
    }
}

PhpRedis ile bağlanma

Aşağıdaki örnek PhpRedis 5.3.7 kullanmaktadır. Daha fazla bilgi için GitHub adresini ziyaret edin.

<?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;
 ?>

redis-py ile bağlanma

Aşağıdaki örnek Python 3.9 ve redis-py 4.4.1 kullanmaktadır. Daha fazla bilgi için GitHub adresini ziyaret edin.

# !/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'))

Spring Data Redis ile bağlanma

Aşağıdaki Maven projesi Spring Data Redis 2.4.2 kullanmaktadır. Alternatif olarak Lettuce veya Jedis istemcisini manuel olarak indirin.

1. Adım: Maven bağımlılıklarını ekleme

<?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>

2. Adım: Bağlantıyı yapılandırma

Altyapı istemcisi olarak Jedis (önerilir) veya Lettuce seçin.

Jedis ile Spring Data Redis (önerilir)

@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);
    }

Lettuce ile Spring Data Redis

Uyarı
/**
     * 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);
    }

.NET (StackExchange.Redis) ile bağlanma

Aşağıdaki örnek .NET 6.0 ve StackExchange.Redis 2.6.90 kullanmaktadır.

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);
    }
}

node-redis ile bağlanma

Aşağıdaki örnek Node.js 19.4.0 ve node-redis 4.5.1 kullanmaktadır.

Kimlik bilgilerini hem rootNodes URL'sinde hem de defaults nesnesinde sağlayın. defaults kimlik bilgileri kalan tüm küme düğümlerine yapılan bağlantıları doğrular. Bunlar olmadan NOAUTH hatası oluşur.

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();

go-redis ile bağlanma

Aşağıdaki örnek Go 1.19.7 ve go-redis 9.5.1 kullanmaktadır.

Önemli

go-redis 9,0 veya üzeri bir sürüm kullanın. Daha eski sürümler özel bir uç nokta üzerinden bağlanırken uyumsuzluk hatalarına neden olabilir. Daha fazla bilgi için bkz. Common errors and troubleshooting.

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)
}

Lettuce (bağımsız) ile bağlanma

Uyarı

1. Adım: Maven bağımlılıklarını ekleme

<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>

2. Adım: Bağlantı kodunu ekleme

host, port ve password değerlerini gerçek örnek bilgileriyle değiştirin.

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"));
    }
}

Başarılı olduğunda beklenen çıktı:

value

Lettuce parametre referansı

Aşağıdaki parametreler Lettuce küme topolojisi yenilemesini ve TCP davranışını kontrol eder. Yanlış varsayılanlar örnek değişiklikleri sırasında artan gecikme süresine ve erişilemezliğe neden olabilir.

Parametre Varsayılan Önerilen Açıklama
enablePeriodicRefresh(Duration) Devre dışı 60 saniye Periyodik küme topolojisi yenilemesini etkinleştirir. Boştaki kalıcı bağlantılar için bile yerel topoloji görünümünü güncel tutar.
dynamicRefreshSources(boolean) true false true olduğunda CLUSTER NODES tarafından döndürülen tüm düğümler topolojiyi yeniler ve bu da sunucu yükünü artırır. false olduğunda yalnızca belirtilen uç nokta kullanılır. Yapılandırma değişiklikleri sırasında uç nokta genellikle daha hızlı ve daha güvenilirdir.
enableAllAdaptiveRefreshTriggers() Devre dışı Etkin (gerekli) Bir MOVED mesajı alındığında otomatik topoloji yenilemesini tetikler. Bu olmadan Lettuce topoloji değişikliğinden sonra yerel topolojiyi güncelleyemez.
adaptiveRefreshTriggersTimeout(Duration) 30 sn 15 sn Topoloji yenileme sıklığını zaman aşımı süresi başına bir yenileme ile sınırlar. Düğümler arasındaki topoloji değişiklikleri atomik değildir bu nedenle ilk yenileme başarısız olabilir. Daha kısa bir zaman aşımı daha hızlı bir takip yenilemesine olanak tanır. İstemci uygulama sayısı az olduğunda bu değeri daha da azaltın.
validateClusterNodeMembership(boolean) true false (gerekli) true olduğunda MOVED yeniden yönlendirmeleri yalnızca CLUSTER NODES çıktısında listelenen düğümlere gider. Yerel topoloji yenilenmeden önce yeni eklenen düğümlere erişime izin vermek için false olarak ayarlayın.

SSS

MOVED 4578 172.18.xx.xxx:6379 hatası neden oluşur?

MOVED <slot> <IP:Port> hatası istenen anahtarın farklı bir düğümde olduğunu gösterir. Bu durum genellikle istemci Redis Cluster protokolünü desteklemediğinde ortaya çıkar. Yaygın senaryolar şunlardır:

  • -c seçeneği olmadan redis-cli ile bağlanma.

  • Python'da otomatik yeniden yönlendirmeyi işlemeyen standart redis-py istemcisini kullanma. Bunun yerine redis.cluster.RedisCluster sınıfını kullanın.

Diğer hatalar hakkında bilgi için bkz. Common errors and troubleshooting.