All Products
Search
Document Center

Tair (Redis® OSS-Compatible):Connect to a Tair Serverless KV instance

Last Updated:Nov 06, 2025

This topic describes how to connect to a Tair Serverless KV instance using redis-cli and code.

Prerequisites

Connect to the instance

Obtain the parameters that are required to connect to the instance from the following table.

Parameter

Description

How to obtain

hostname

Endpoint

  1. Go to the Instances page, select a region in the top navigation bar, and then click the ID of the target instance.

  2. In the Connection Information area at the bottom of the Instance Information page, you can obtain the connection address and port number.

port

Port number

The default port number is 6379. You can also customize the port number. For more information, see Modify an endpoint or port number.

password

Password

Enter the username and password based on the account type:

  • Default account (usually default or an account named after the instance ID): Enter only the password.

  • Standard account: The password format is user:password. For example, if the custom username is testaccount and the password is Rp829dlwa, you must enter the password as testaccount:Rp829dlwa.

If you forget the password or have not set one, you can change or reset the password.

Note

Tair Serverless KV uses a distributed architecture and is compatible with the native Redis Cluster protocol, connection method, and usage. You must make sure that your client connects to the instance in Redis Cluster mode.

Connect using code

Jedis

In this example, Jedis 4.3.0 is used. For more information, visit GitHub.

  • Custom connection pool (recommended)

    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[]) {
            // Specify the maximum number of connections. In direct connection mode, the client directly connects to a shard of a cluster instance. Therefore, the following requirement must be met: Number of clients × Value of MaxTotal < Maximum number of connections to a single shard. 
            config.setMaxTotal(30);
            // Specify the maximum number of idle connections based on your business needs. 
            config.setMaxIdle(20);
            config.setMinIdle(15);
    
            // Specify the private endpoint that is allocated to the cluster instance. 
            String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com";
            int port = 6379;
            // Specify the password that is used to connect to 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();     // If the application exits and you want to destroy the resources, call this method. This way, the connection is closed, and the resources are released. 
        }
    }
  • Default connection pool

    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[]){
    
            // Specify the private endpoint that is allocated to 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();     // If the application exits and you want to destroy the resources, call this method. This way, the connection is closed, and the resources are released. 
        }
    }

Spring Data Redis

The following sample project is created by using Maven. You can also manually download the Lettuce or Jedis client.

  1. Add the following Maven dependencies:

    <?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. Enter the following code in the Spring Data Redis editor and modify the code based on the comments.

    In this example, Spring Data Redis 2.4.2 is used.

    • (Recommended) Spring Data Redis with Jedis

      @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();
               // Specify the maximum number of idle connections. In direct connection mode, the client directly connects to a shard of a cluster instance. Therefore, the following requirement must be met: Number of clients × Value of MaxTotal < Maximum number of connections to a single shard. 
               jedisPoolConfig.setMaxTotal(30);
               // Specify the maximum number of idle connections based on your business needs. 
               jedisPoolConfig.setMaxIdle(20);
               // Disable testOn[Borrow|Return] to prevent generating additional ping commands.
               jedisPoolConfig.setTestOnBorrow(false);
               jedisPoolConfig.setTestOnReturn(false);
       
               return new JedisConnectionFactory(redisClusterConfiguration, jedisPoolConfig);
           }
    • Spring Data Redis With Lettuce

      Warning
      • The default configurations of Lettuce may cause issues such as increased application latency and inaccessibility when the instance is changed. To properly configure Lettuce, carefully read the description of Lettuce-related parameters.

      • The version of Lettuce must be 6.3.0.RELEASE or later. For more information, see [Notice] Suggestions for upgrading Lettuce.

           /**
           * 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;
      
          /**
           * You can use the TCP_USER_TIMEOUT parameter to avoid scenarios in which 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);
          }

PhpRedis

In this example, PhpRedis 5.3.7 is used. For more information, visit GitHub.

<?php
 // Specify the private endpoint and port number that are used to connect to the cluster instance. 
 $array = ['r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379'];
 // Specify the password that is used to connect to the cluster instance. 
 $pwd = "xxxx";
 
 // Use the password to connect to the cluster instance. 
 $obj_cluster = new RedisCluster(NULL, $array, 1.5, 1.5, true, $pwd);
 
 // Display the result of the connection. 
 var_dump($obj_cluster);
 
 if ($obj_cluster->set("foo", "bar") == false) {
     die($obj_cluster->getLastError());
 }
 $value = $obj_cluster->get("foo");
 echo $value;
 ?>

redis-py

In this example, Python 3.9 and redis-py 4.4.1 are used. For more information, visit GitHub.

# !/usr/bin/env python
# -*- coding: utf-8 -*-
from redis.cluster import RedisCluster
# Replace the values of the host and port parameters with the endpoint and port number that are used to connect to the instance. 
host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com'
port = 6379
# Replace the values of the user and pwd parameters with the username and password that are used to connect to the instance. 
user = 'testaccount'
pwd = 'Rp829dlwa'
rc = RedisCluster(host=host, port=port, username=user, password=pwd)
# You can perform operations on the instance after the connection is established. The following code provides an example on how to call the set and get methods: 
rc.set('foo', 'bar')
print(rc.get('foo'))

.NET

In this example, .NET 6.0 and StackExchange.Redis 2.6.90 are used.

using StackExchange.Redis;

class RedisConnSingleton {
    // Specify the endpoint, port number, username, and password that are used to connect to 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

In this example, Node.js 19.4.0 and node-redis 4.5.1 are used.

import { createCluster } from 'redis';

// Specify the endpoint, port number, username, and password that are used to connect to the instance. 
// After you supply the username and password for the url parameter, you must also supply the global username and password for the defaults parameter. 
// The global username and password are used to authenticate the remaining nodes. If the remaining nodes are not authenticated, the 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

In this example, Go 1.19.7 and go-redis 9.5.1 are used.

Important

Use go-redis 9.0 or later. If you use a go-redis version earlier than 9.0, an incompatibility error may occur when you connect to a private endpoint. For more information, see 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

Warning
  • The default configurations of Lettuce may cause issues such as increased application latency and inaccessibility when the instance is changed. To properly configure Lettuce, carefully read the description of Lettuce-related parameters.

  • The version of Lettuce must be 6.3.0.RELEASE or later. For more information, see [Notice] Suggestions for upgrading Lettuce.

  1. Add the following Maven dependencies:

            <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. Add the following code and modify the code based on the comments:

    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;
    
        /**
         * The TCP_USER_TIMEOUT parameter can avoid 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 the values of host, port, and password 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"));
        }
    }
  3. Run the preceding code. The following output is expected on successful completion:

    value

The following table describes Lettuce-related parameters.

Parameter

Default configuration

Description

Recommended configuration

enablePeriodicRefresh(Duration refreshPeriod)

Disabled

Enables periodic cluster topology refresh.

We recommend that you set the refresh period to 60 seconds.

Enabling this option ensures that even inactive persistent connections maintain an up-to-date view of the local topology.

dynamicRefreshSources(boolean dynamicRefreshSources)

true

If this parameter is set to true, all nodes returned by the Cluster Nodes command are used to refresh the cluster topology. If this parameter is set to false, the specified node endpoint is used.

We recommend that you set this parameter to false unless otherwise required.

If you enable this option, the CLUSTER NODES command is sent to all nodes, which increases the load on the server. In addition, during configuration changes, using endpoints to update the topology is typically faster and more reliable.

enableAllAdaptiveRefreshTriggers()

Disabled

Enables automatic cluster topology refresh upon receiving a MOVED message.

This parameter must be enabled.

Enabling this option ensures that Lettuce can promptly update the local topology after a topology change.

adaptiveRefreshTriggersTimeout(Duration timeout)

30s

Limits the frequency of cluster topology refreshes to allow only one refresh within the specified timeout period.

We recommend that you set this parameter to 15s.

Topology changes across multiple nodes in a cluster are not atomic. As a result, the first topology refresh triggered by Lettuce may fail. A quick subsequent refresh helps ensure that the topology is updated correctly. When the number of applications is small, fewer clients send the CLUSTER NODES command at the same time. In this case, you can appropriately reduce this value to achieve faster convergence of the topology table.

validateClusterNodeMembership(boolean validateClusterNodeMembership)

true

During a topology change, Lettuce uses MOVED to redirect commands to the correct nodes. After this parameter is set to true, commands can be redirected only to nodes that are explicitly listed in the CLUSTER NODES command output.

This parameter must be set to false.

Setting this parameter to false allows access to newly added nodes before local topology refreshes are completed after a cluster topology change.

Connect using redis-cli

  1. Connect to the instance:

    ./redis-cli -h r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com -p 6379 -c
  2. Authenticate with your password.

    AUTH testaccount:Rp829dlwa

For more information about redis-cli, see Connect to an instance using redis-cli.

FAQ

  • Q: What can I do if my ECS and Tair Serverless KV instances are not in the same VPC?

    A: You can change the VPC of the ECS instance to the VPC of the Tair instance, or create a Tair Serverless KV instance in the same VPC as the ECS instance.