Tair (Redis OSS-compatible) instances are fully compatible with open-source Redis. Connect using any Redis-compliant client the same way you connect to a Redis database.
Usage notes
-
Cluster and read/write splitting architectures: Both provide a proxy node endpoint by default. Connect to these instances the same way you connect to a standard-architecture instance.
When connecting via a direct connection endpoint, use the same method as connecting to an open-source Redis cluster.
-
Password-free access: If password-free access over a VPC is enabled, clients in the same VPC can connect without a password.
Get connection information
Before writing code, collect the following connection details from the Instances page. Select your region in the top navigation bar, click the instance ID, and go to the Connection Information section.
| Detail |
How to get it |
| Endpoint |
View endpoints and ports in the Connection Information section. Use VPC endpoints for better security and lower latency. See View endpoints. |
| Port |
Default is 6379. To change it, see Change an endpoint or port. |
| Account |
By default, each instance has an account named after the instance ID (for example, r-bp10noxlhcoim2****). To create additional accounts, see Create and manage accounts. |
| Password |
The format depends on the account type: default account — enter the password directly; custom account — use <username>:<password> (for example, testaccount:Rp829dlwa). |
When using third-party tools such as Remote Desktop Manager (RDM), enter the password in username:password format. To reset a forgotten password, see Change or reset the password.
Choose a client
Pick the client for your language. All examples in the next section connect to the same Tair instance.
| Language |
Client |
API style |
Notes |
| Java |
Jedis |
Synchronous |
Connection pooling via JedisPool |
| Java |
Lettuce |
Async and reactive |
Use version 6.3.0.RELEASE or later |
| Java |
Spring Data Redis |
Synchronous or async |
Supports both Jedis and Lettuce backends |
| Python |
redis-py |
Synchronous |
Official Python client |
| Node.js |
node-redis |
Async |
Official Node.js client |
| Go |
go-redis |
Synchronous |
Widely used Go client |
| PHP |
PhpRedis |
Synchronous |
C extension for PHP |
| C / C++ |
hiredis |
Synchronous |
Minimalist C client |
| .NET |
StackExchange.Redis |
Synchronous |
Use version 2.7.20 or later |
For the full list of supported clients, see Redis Clients.
Important
Do not use the ServiceStack Redis or CSRedis client. ServiceStack Redis issues require purchasing support from ServiceStack directly, and CSRedis support has ended.
Connect and test
The following examples show the minimum code needed to connect and run a SET/GET command. Replace all placeholder values with your actual connection details.
Jedis
This example uses Jedis 4.3.0.
This example uses Maven. You can also download the Jedis JAR directly.
-
Add the dependency to pom.xml:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>
-
Connect and run commands:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisExample {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
// Max idle connections — must not exceed the instance's connection limit
config.setMaxIdle(200);
// Max total connections — must not exceed the instance's connection limit
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
// Replace with your instance endpoint and password
String host = "r-bp1s1bt2tlq3p1****pd.redis.rds.aliyuncs.com";
// Default account: enter password directly
// Custom account: use "username:password" format
String password = "r-bp1s1bt2tlq3p1****:Database123";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set("foo10", "bar");
System.out.println(jedis.get("foo10"));
jedis.zadd("sose", 0, "car");
jedis.zadd("sose", 0, "bike");
System.out.println(jedis.zrange("sose", 0, -1));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
// Call this when shutting down your application to release resources
pool.destroy();
}
}
-
Expected output:
bar
[bike, car]
Important
For Jedis errors caused by invalid parameters or improper feature usage, see Common errors.
Lettuce
This example uses Lettuce 6.3.0.RELEASE.
Important
Use Lettuce 6.3.0.RELEASE or later and set the TCP_USER_TIMEOUT parameter. This prevents blackhole filtering issues on the Lettuce client.
This example uses Maven. You can also download the Lettuce JAR directly.
-
Add the following dependencies to pom.xml:
<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.100.Final</version>
<classifier>linux-x86_64</classifier>
</dependency>
</dependencies>
-
Connect and run commands:
import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.SocketOptions.KeepAliveOptions;
import io.lettuce.core.SocketOptions.TcpUserTimeoutOptions;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import java.time.Duration;
public class LettuceExample {
/**
* Enable TCP keepalive with these settings:
* TCP_KEEPIDLE = 30 seconds
* TCP_KEEPINTVL = 10 seconds
* TCP_KEEPCNT = 3
*/
private static final int TCP_KEEPALIVE_IDLE = 30;
/**
* TCP_USER_TIMEOUT prevents Lettuce from getting stuck in a timeout loop
* during a failure or crash. See: https://github.com/lettuce-io/lettuce-core/issues/2082
*/
private static final int TCP_USER_TIMEOUT = 30;
private static RedisClient client = null;
private static StatefulRedisConnection<String, String> connection = null;
public static void main(String[] args) {
// Replace with your actual instance information
String host = "r-bp1s1bt2tlq3p1****.redis.rds.aliyuncs.com";
String user = "r-bp1s1bt2tlq3p1****";
String password = "Da****3";
int port = 6379;
// Build RedisURI
RedisURI uri = RedisURI.Builder
.redis(host, port)
.withAuthentication(user, password)
.build();
// Configure TCP keepalive and TCP_USER_TIMEOUT
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();
client = RedisClient.create(uri);
client.setOptions(ClientOptions.builder()
.socketOptions(socketOptions)
.build());
connection = client.connect();
RedisCommands<String, String> commands = connection.sync();
System.out.println(commands.set("foo", "bar"));
System.out.println(commands.get("foo"));
// Shut down — closes the connection and releases resources
connection.close();
client.shutdown();
}
}
-
Expected output:
OK
bar
Spring Data Redis
This example uses Spring Data Redis 2.4.2.
Important
Use Lettuce version 6.3.0.RELEASE or later and set TCP_USER_TIMEOUT to prevent blackhole filtering issues.
This example uses Maven with either Lettuce or Jedis as the connection backend.
-
Add the following to pom.xml:
<?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/>
</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>
-
Configure the connection factory. Choose Jedis or Lettuce: Spring Data Redis with Jedis:
@Bean
JedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("host", port);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// Max total connections — must not exceed the instance's connection limit
jedisPoolConfig.setMaxTotal(30);
// Max idle connections — must not exceed the instance's connection limit
jedisPoolConfig.setMaxIdle(20);
// Disable testOn[Borrow|Return] to avoid extra PING commands
jedisPoolConfig.setTestOnBorrow(false);
jedisPoolConfig.setTestOnReturn(false);
JedisClientConfiguration jedisClientConfiguration = JedisClientConfiguration.builder()
.usePooling()
.poolConfig(jedisPoolConfig)
.build();
return new JedisConnectionFactory(config, jedisClientConfiguration);
}
Spring Data Redis with Lettuce (includes TCP_USER_TIMEOUT):
@Configuration
public class BeanConfig {
/**
* Enable TCP keepalive with these settings:
* TCP_KEEPIDLE = 30 seconds
* TCP_KEEPINTVL = 10 seconds
* TCP_KEEPCNT = 3
*/
private static final int TCP_KEEPALIVE_IDLE = 30;
/**
* TCP_USER_TIMEOUT prevents Lettuce from getting stuck in a timeout loop
* during a failure or crash. See: https://github.com/lettuce-io/lettuce-core/issues/2082
*/
private static final int TCP_USER_TIMEOUT = 30;
@Bean
LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName("r-bp1y4is8svonly****pd.redis.rds.aliyuncs.com");
config.setPort(6379);
config.setUsername("r-bp1y4is8svonly****");
config.setPassword("Da****3");
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();
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.clientOptions(ClientOptions.builder().socketOptions(socketOptions).build())
.build();
return new LettuceConnectionFactory(config, lettuceClientConfiguration);
}
@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
-
Run the code.
redis-py
This example uses Python 3.9 and redis-py 4.4.1.
-
Download and install the redis-py client.
-
Connect and run commands:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import redis
# Replace with your instance endpoint and port
host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com'
port = 6379
# Default account: enter password directly
# Custom account: use "username:password" format
pwd = 'testaccount:Rp829dlwa'
r = redis.Redis(host=host, port=port, password=pwd)
r.set('foo', 'bar')
print(r.get('foo'))
-
Run the script.
node-redis
This example uses Node.js 19.4.0 and node-redis 4.5.1.
-
Download and install node-redis.
-
Connect and run commands:
import { createClient } from 'redis';
// Replace with your instance endpoint, port, account, and password
const host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com';
const port = 6379;
const username = 'testaccount';
// If the password contains special characters (!@#$%^&*()+-=_), encode it first:
// password = encodeURIComponent(password)
const password = 'Rp829dlwa';
const client = createClient({
// redis://[[username]:[password]@[host][:port]/[db-number]
url: `redis://${username}:${password}@${host}:${port}/0`
});
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();
await client.set('foo', 'bar');
const value = await client.get('foo');
console.log("get foo: %s", value);
await client.disconnect();
-
Run the script.
If you see SyntaxError: Cannot use import statement outside a module, rename the file from .js to .mjs and run it with node --experimental-modules redis.mjs.
go-redis
This example uses Go 1.18.5 and go-redis 8.11.5.
-
Download and install the go-redis client.
-
Connect and run commands:
package main
import (
"github.com/go-redis/redis"
"fmt"
)
func ExampleClient() {
client := redis.NewClient(&redis.Options{
// Replace with your instance endpoint and port
Addr: "r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379",
// Replace with your instance password
Password: "testaccount:Rp829dlwa",
DB: 0,
})
err := client.Set("foo", "bar", 0).Err()
if err != nil {
panic(err)
}
val, err := client.Get("foo").Result()
if err != nil {
panic(err)
}
fmt.Println("set : foo -> ", val)
}
func main() {
ExampleClient()
}
-
Run the code.
PhpRedis
This example uses PHP 8.2.1 and PhpRedis 5.3.7.
-
Download and install the PhpRedis client.
-
Connect and run commands:
<?php
// Replace with your instance endpoint and port
$host = "r-bp10noxlhcoim2****.redis.rds.aliyuncs.com";
$port = 6379;
// Replace with your account and password
$user = "testaccount";
$pwd = "Rp829dlwa";
$redis = new Redis();
if ($redis->connect($host, $port) == false) {
die($redis->getLastError());
}
if ($redis->auth([$user, $pwd]) == false) {
die($redis->getLastError());
}
if ($redis->set("foo", "bar") == false) {
die($redis->getLastError());
}
$value = $redis->get("foo");
echo $value;
?>
-
Run the script.
Common errors:
Cannot assign requested address: See The "Cannot assign requested address" error.
redis protocol error, got ' ' as reply type byte: Upgrade your PhpRedis client. See phpredis/phpredis#1585.
C or C++
This example uses hiredis 1.1.0.
-
Download and install hiredis.
-
Write the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
int main(int argc, char **argv) {
unsigned int j;
redisContext *c;
redisReply *reply;
if (argc < 4) {
printf("Usage: example r-bp10noxlhcoim2****.redis.rds.aliyuncs.com 6379 instance_id password\n");
exit(0);
}
const char *hostname = argv[1];
const int port = atoi(argv[2]);
const char *instance_id = argv[3];
const char *password = argv[4];
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
c = redisConnectWithTimeout(hostname, port, timeout);
if (c == NULL || c->err) {
if (c) {
printf("Connection error: %s\n", c->errstr);
redisFree(c);
} else {
printf("Connection error: can't allocate redis context\n");
}
exit(1);
}
/* AUTH */
reply = redisCommand(c, "AUTH %s", password);
printf("AUTH: %s\n", reply->str);
freeReplyObject(reply);
/* PING */
reply = redisCommand(c, "PING");
printf("PING: %s\n", reply->str);
freeReplyObject(reply);
/* SET and GET */
reply = redisCommand(c, "SET %s %s", "foo", "hello world");
printf("SET: %s\n", reply->str);
freeReplyObject(reply);
reply = redisCommand(c, "SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5);
printf("SET (binary API): %s\n", reply->str);
freeReplyObject(reply);
reply = redisCommand(c, "GET foo");
printf("GET foo: %s\n", reply->str);
freeReplyObject(reply);
/* INCR */
reply = redisCommand(c, "INCR counter");
printf("INCR counter: %lld\n", reply->integer);
freeReplyObject(reply);
reply = redisCommand(c, "INCR counter");
printf("INCR counter: %lld\n", reply->integer);
freeReplyObject(reply);
/* List operations */
reply = redisCommand(c, "DEL mylist");
freeReplyObject(reply);
for (j = 0; j < 10; j++) {
char buf[64];
snprintf(buf, 64, "%d", j);
reply = redisCommand(c, "LPUSH mylist element-%s", buf);
freeReplyObject(reply);
}
reply = redisCommand(c, "LRANGE mylist 0 -1");
if (reply->type == REDIS_REPLY_ARRAY) {
for (j = 0; j < reply->elements; j++) {
printf("%u) %s\n", j, reply->element[j]->str);
}
}
freeReplyObject(reply);
/* Disconnect and free context */
redisFree(c);
return 0;
}
-
Compile:
gcc -o example -g example.c -I /usr/local/include/hiredis -lhiredis
-
Run:
./example r-bp10noxlhcoim2****.redis.rds.aliyuncs.com 6379 r-bp10noxlhcoim2**** password
.NET (StackExchange.Redis)
This example uses StackExchange.Redis 2.7.20.
-
Download and install StackExchange.Redis.
-
Set up a singleton ConnectionMultiplexer:
ConfigurationOptions should be configured as a singleton and shared across your application. For all available parameters, see ConfigurationOptions. The IDatabase object returned by GetDatabase() is lightweight — create it on each use from the ConnectionMultiplexer: ``csharp redisConn = GetRedisConn(); var db = redisConn.GetDatabase(); ``
using StackExchange.Redis;
// Set the endpoint, port, and password
private static ConfigurationOptions configurationOptions = ConfigurationOptions.Parse(
"r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379,password=testaccount:Rp829dlwa,connectTimeout=2000"
);
private static readonly object Locker = new object();
private static ConnectionMultiplexer redisConn;
public static ConnectionMultiplexer GetRedisConn()
{
if (redisConn == null)
{
lock (Locker)
{
if (redisConn == null || !redisConn.IsConnected)
{
redisConn = ConnectionMultiplexer.Connect(configurationOptions);
}
}
}
return redisConn;
}
-
Run commands on common data types: String:
String
// SET and GETstring strKey = "hello";string strValue = "world";bool setResult = db.StringSet(strKey, strValue);Console.WriteLine("set " + strKey + " " + strValue + ", result is " + setResult);// INCRstring counterKey = "counter";long counterValue = db.StringIncrement(counterKey);Console.WriteLine("incr " + counterKey + ", result is " + counterValue);// EXPIREdb.KeyExpire(strKey, new TimeSpan(0, 0, 5));Thread.Sleep(5 * 1000);Console.WriteLine("expire " + strKey + ", after 5 seconds, value is " + db.StringGet(strKey));// MSET and MGETKeyValuePair<RedisKey, RedisValue> kv1 = new KeyValuePair<RedisKey, RedisValue>("key1", "value1");KeyValuePair<RedisKey, RedisValue> kv2 = new KeyValuePair<RedisKey, RedisValue>("key2", "value2");db.StringSet(new KeyValuePair<RedisKey, RedisValue>[] { kv1, kv2 });RedisValue[] values = db.StringGet(new RedisKey[] { kv1.Key, kv2.Key });Console.WriteLine("mget " + kv1.Key + " " + kv2.Key + ", result is " + values[0] + "&&" + values[1]);
Hash
string hashKey = "myhash";db.HashSet(hashKey, "f1", "v1");db.HashSet(hashKey, "f2", "v2");HashEntry[] values = db.HashGetAll(hashKey);Console.Write("hgetall " + hashKey + ", result is");for (int i = 0; i < values.Length; i++){ HashEntry hashEntry = values[i]; Console.Write(" " + hashEntry.Name + " " + hashEntry.Value);}Console.WriteLine();
List
string listKey = "myList";db.ListRightPush(listKey, "a");db.ListRightPush(listKey, "b");db.ListRightPush(listKey, "c");RedisValue[] values = db.ListRange(listKey, 0, -1);Console.Write("lrange " + listKey + " 0 -1, result is ");for (int i = 0; i < values.Length; i++){ Console.Write(values[i] + " ");}Console.WriteLine();
Set
string setKey = "mySet";db.SetAdd(setKey, "a");db.SetAdd(setKey, "b");db.SetAdd(setKey, "c");bool isContains = db.SetContains(setKey, "a");Console.WriteLine("set " + setKey + " contains a is " + isContains);
Sorted Set
string sortedSetKey = "myZset";db.SortedSetAdd(sortedSetKey, "xiaoming", 85);db.SortedSetAdd(sortedSetKey, "xiaohong", 100);db.SortedSetAdd(sortedSetKey, "xiaofei", 62);db.SortedSetAdd(sortedSetKey, "xiaotang", 73);RedisValue[] names = db.SortedSetRangeByRank(sortedSetKey, 0, 2, Order.Ascending);Console.Write("zrevrangebyscore " + sortedSetKey + " 0 2, result is ");for (int i = 0; i < names.Length; i++){ Console.Write(names[i] + " ");}Console.WriteLine();