
Alibabacloud Tair Devtoolset
- 158 installs
- 208 repo stars
- Updated August 4, 2026
- aliyun/alibabacloud-aiops-skills
Integrate and debug Alibaba Cloud Tair cache clusters during development, including key patterns, connection setup, and troubleshooting Redis-compatible operations from agent-assisted coding sessions.
About
Alibaba Cloud Tair devtoolset skill that guides agents through developing against Tair cache clusters. It covers integration setup, Redis-compatible command usage, local and cloud debugging patterns, and faster iteration when adding caching to backend services.
- Tair connection setup
- Redis-compatible operations
- Cache key design help
- Dev-time cluster debugging
- Managed in-memory store
Alibabacloud Tair Devtoolset by the numbers
- 158 all-time installs (skills.sh)
- Ranked #257 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aliyun/alibabacloud-aiops-skills --skill alibabacloud-tair-devtoolsetAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 158 |
|---|---|
| repo stars | ★ 208 |
| Last updated | August 4, 2026 |
| Repository | aliyun/alibabacloud-aiops-skills ↗ |
What it does
Integrate and debug Alibaba Cloud Tair cache clusters during development, including key patterns, connection setup, and troubleshooting Redis-compatible operations from agent-assisted coding sessions.
Files
Tair DevToolset — Full-Lifecycle Tair Development Assistant
This Skill provides operational capabilities and development guidelines for Alibaba Cloud Tair (Redis OSS-Compatible) database, covering architecture selection, data structure design, instance creation, connection management, performance monitoring, error troubleshooting, and backup & recovery.
Note: This Skill executes real cloud operations via aliyun CLI. Restore operations are high-risk and will overwrite current data. Ensure the RAM account has the required permissions before use.
Supported Capabilities
| Capability | Description |
|---|---|
| Architecture Selection | Choose the right Tair architecture (Standard vs Cluster) and edition (Memory-optimized, Persistent memory, Disk-based) |
| Data Structure Design | Select optimal Redis and Tair extended data structures for your use case |
| Instance Creation | Create and configure Tair instances via aliyun CLI |
| Connection Management | Connect via standalone/proxy/cluster modes with TLS support |
| Performance Monitoring | Intelligent diagnostics via alibabacloud-tair-ai-assistant skill |
| Error Troubleshooting | Diagnose and resolve common Tair connection, cluster, memory, and client errors |
| Backup and Recovery | Configure backup policies, perform PITR, and restore data |
---
Part I — Cross-Cutting Concerns
1. Prerequisites
1.1 CLI Installation & Version
Aliyun CLI >= 3.3.3 required. Run aliyun version to verify. If not installed or version too low, see references/cli-installation-guide.md for installation instructions.
# Enable automatic plugin installation (required for r-kvstore plugin)
aliyun configure set --auto-plugin-install true
# Update existing plugins to latest version
aliyun plugin update
# Verify jq is installed (required for JSON parsing in scripts)
jq --version1.2 Authentication
All credential configurations follow existing aliyun CLI settings.
Security Rules:
- NEVER read, echo, or print AK/SK values (e.g.,
echo $ALIBABA_CLOUD_ACCESS_KEY_IDis FORBIDDEN) - NEVER ask the user to input AK/SK directly in the conversation or command line
- NEVER use
aliyun configure setwith literal credential values - ONLY use
aliyun configure listto check credential status
aliyun configure listIf no valid profile exists, STOP here. Configure credentials outside of this session, then return.
1.3 AI-Mode Configuration
[MUST] Enable AI-Mode at the start of any workflow (before any CLI invocation):
```bash
aliyun configure ai-mode enable
aliyun configure ai-mode set-user-agent --user-agent "AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolset"
```
[MUST] Disable AI-Mode at EVERY exit point — before delivering the final response for ANY reason (success, failure, error, user cancellation, etc.). AI-mode MUST NOT remain enabled after the skill stops running.
```bash
aliyun configure ai-mode disable
```
2. Security & Compliance
2.1 User-Agent Requirement
Every aliyun CLI command invocation must include:
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolset2.2 RAM Permissions
This Skill requires R-KVStore RAM permissions for instance management, backup, and recovery operations. See references/ram-policies.md for the full permission table and policy document.
[MUST] Permission Failure Handling: When any command fails due to permission errors:
1. Read references/ram-policies.md to get the full list of required permissions2. Use ram-permission-diagnose skill to guide the user through requesting permissions3. Pause and wait until the user confirms that the required permissions have been granted
3. Parameter Confirmation Rule
Before executing any command or API call, ALL user-customizable parameters (e.g., RegionId, instance names, passwords, resource specifications) MUST be confirmed with the user. Do NOT assume or use default values without explicit user approval.
---
Part II — Capabilities
4. Architecture Selection
Choose the right Tair architecture based on data volume, throughput requirements, and read/write ratio.
When to Use
- Deciding between Standard and Cluster architecture
- Determining whether read/write splitting is needed
- Selecting edition type (Memory-optimized, Persistent memory, Disk-based)
- Evaluating Tair vs Open Source Redis for a new project
Key Guidance
Key Concepts:
| Component | Description |
|---|---|
| Node | Smallest unit, runs Redis-compatible process |
| Shard | Group of nodes storing a subset of data |
| Master node | Handles write operations |
| Replica node | Copy of master, provides failover |
| Read-only node | Serves read traffic only (read/write splitting) |
| Proxy node | Routes requests to appropriate nodes |
Architecture Comparison:
| Dimension | Standard | Cluster |
|---|---|---|
| Structure | One master + replicas | Multiple shards, each with master + replicas |
| Data partitioning | No (single shard) | Yes (distributed across shards) |
| Best for | Small data, stable QPS | Large data, high QPS, throughput-intensive |
| Read/write splitting | Supported | Supported |
Selection Decision Tree:
Data volume > single-node capacity?
├── Yes → Cluster architecture
│ └── Read-heavy? → Enable read/write splitting
└── No → Standard architecture
└── Read-heavy? → Enable read/write splittingReferences
- references/architecture-selection/arch-selection.md — Architecture selection decision guide
- references/architecture-selection/arch-compare-oss-redis.md — Tair vs Open Source Redis comparison and edition selection
---
5. Data Structure Design
Choose the appropriate data structure based on your access patterns and business requirements.
When to Use
- Selecting data structures for a new feature or application
- Choosing between Redis native and Tair extended data structures
- Migrating data models and evaluating structure alternatives
Key Guidance
Redis Data Structures:
| Name | Use Case |
|---|---|
| String | Caching, counters, distributed locks, session storage, rate limiting |
| Hash | Object storage (user profiles, product info), grouped field-value pairs |
| List | Message queues, latest feeds, task queues, stack/queue operations |
| Set | Unique collections, tagging, social graph (followers/friends), set operations |
| Sorted Set | Leaderboards, ranking systems, priority queues, range queries by score |
| Stream | Event sourcing, log streaming, message queues with consumer groups |
| Bitmap | Feature flags, online status tracking, daily active user counting |
| Bitfield | Compact counters, fixed-width integer encoding, atomic increment |
| Geospatial | Location-based services, nearby search, geofencing |
| HyperLogLog | Unique visitor counting, cardinality estimation with minimal memory |
Tair Data Structures:
| Name | Use Case |
|---|---|
| exString / TairString (String enhancement) | Versioned strings, bounded INCRBY, CAS/CAD for distributed locks |
| exHash / TairHash (Hash enhancement) | Field-level TTL, field versioning, multi-device login management |
| exZset / TairZset (Zset enhancement) | Multi-dimensional scoring (256 dims), multi-criteria ranking |
| GIS / TairGis (Geospatial enhancement) | Point/line/polygon queries, spatial relationship checks |
| Doc / TairDoc (JSON) | JSON with binary tree indexing, fast sub-element access |
| Search / TairSearch | ES-like full-text search, multi-column index, tokenization |
| TS / TairTs (TimeSeries) | Real-time monitoring, IoT data, two-level timeline aggregation |
| Bloom / TairBloom | Probabilistic membership testing, deduplication, URL filtering |
| Cpc / TairCpc | Compressed cardinality estimation, streaming analytics |
| Roaring / TairRoaring (Bitmap enhancement) | User segmentation, audience targeting, multi-bitmap operations |
| Vector / TairVector | Vector similarity search, LLM Chatbot, multimodal retrieval |
References
- references/data-structure-design/data-structure-design.md — Detailed data structure use case descriptions
- Redis Data Types
- Tair Extended Data Structures
---
6. Instance Creation
Create and configure Tair instances on Alibaba Cloud, including whitelist configuration and public endpoint allocation.
When to Use
- Creating a new Tair instance for testing, development, or production
- Configuring network access (whitelist, public endpoint) for an instance
- Setting up a Tair benchmark or PoC environment
6.1 Choosing Instance Specifications
Required Parameters:
| Parameter | Description | Example |
|---|---|---|
| VPC_ID | VPC ID | vpc-bp1xxx |
| VSWITCH_ID | VSwitch ID | vsw-bp1xxx |
Optional Parameters (with defaults):
| Parameter | Default | Description |
|---|---|---|
| REGION_ID | cn-hangzhou | Region ID |
| ZONE_ID | cn-hangzhou-h | Zone ID |
| INSTANCE_TYPE | tair_rdb | Instance series: tair_rdb (DRAM), tair_scm (Persistent memory), tair_essd (ESSD disk) |
| INSTANCE_CLASS | tair.rdb.1g | Instance specification (see table below) |
| INSTANCE_NAME | tair-benchmark-<timestamp> | Instance name |
| CHARGE_TYPE | PostPaid | Billing method: PostPaid (pay-as-you-go), PrePaid (subscription) |
Common Specifications (Standard Architecture):
| InstanceClass | Memory | Bandwidth | Max Connections | QPS Reference |
|---|---|---|---|---|
| tair.rdb.1g | 1 GB | 768 Mbps | 30,000 | 300,000 |
| tair.rdb.2g | 2 GB | 768 Mbps | 30,000 | 300,000 |
| tair.rdb.4g | 4 GB | 768 Mbps | 40,000 | 300,000 |
| tair.rdb.8g | 8 GB | 768 Mbps | 40,000 | 300,000 |
| tair.rdb.16g | 16 GB | 768 Mbps | 40,000 | 300,000 |
| tair.rdb.24g | 24 GB | 768 Mbps | 50,000 | 300,000 |
| tair.rdb.32g | 32 GB | 768 Mbps | 50,000 | 300,000 |
| tair.rdb.64g | 64 GB | 768 Mbps | 50,000 | 300,000 |
6.2 Automated Workflow (Script)
For quick end-to-end instance creation with public network access, use the all-in-one script:
Execution Constraints:
- MUST usescripts/create-and-connect-test.shfor this workflow — do NOT bypass the script to directly call individualaliyun r-kvstorecommands
- DO NOT write or concatenate aliyun CLI commands to replace script functionality
- Model's responsibility: collect parameters → set environment variables → run script
export VPC_ID="<user-confirmed VPC_ID>"
export VSWITCH_ID="<user-confirmed VSWITCH_ID>"
# Optional parameters
export REGION_ID="cn-hangzhou"
export ZONE_ID="cn-hangzhou-h"
export INSTANCE_TYPE="tair_rdb"
export INSTANCE_CLASS="tair.rdb.1g"
# For NAT environment, manually set public IP
# export MY_PUBLIC_IP="your-public-ip"
bash scripts/create-and-connect-test.shThe script will automatically complete: Create instance → Wait for ready → Configure whitelist → Allocate public endpoint → Get public connection info.
6.3 Manual CLI Steps
For custom requirements (PrePaid subscription, no public endpoint, custom security groups, etc.), use manual CLI steps:
Step 1 — Create instance:
aliyun r-kvstore create-tair-instance \
--biz-region-id "$REGION_ID" --zone-id "$ZONE_ID" \
--vpc-id "$VPC_ID" --vswitch-id "$VSWITCH_ID" \
--instance-type "$INSTANCE_TYPE" --instance-class "$INSTANCE_CLASS" \
--password "$PASSWORD" --charge-type "$CHARGE_TYPE" \
--shard-type "MASTER_SLAVE" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetStep 2 — Wait for instance ready (poll until InstanceStatus is Normal):
aliyun r-kvstore describe-instance-attribute \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetStep 3 — Configure whitelist:
aliyun r-kvstore modify-security-ips \
--instance-id "$INSTANCE_ID" --security-ips "$MY_PUBLIC_IP" \
--security-ip-group-name "default" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetStep 4 — Allocate public endpoint:
aliyun r-kvstore allocate-instance-public-connection \
--instance-id "$INSTANCE_ID" \
--connection-string-prefix "${INSTANCE_ID}pub" --port "6379" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolset6.4 Success Verification
aliyun r-kvstore describe-instance-attribute \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetConfirm InstanceStatus is Normal and public endpoint is allocated. For the full 3-step verification (instance status, whitelist, public endpoint), see references/verification-method.md.
References
- references/instance-creation/connect-create-instance.md — End-to-end instance creation and connection guide with redis-cli examples
- references/related-commands.md — Complete CLI command and parameter reference
- references/verification-method.md — Detailed success verification steps
- references/acceptance-criteria.md — CLI command correctness standards
---
7. Connection Management
Connect to Tair instances using various Redis-compatible clients in standalone, proxy, cluster, or TLS modes.
When to Use
- Connecting to a Tair instance from application code
- Choosing the right client library and connection mode
- Configuring TLS/SSL encryption for secure connections
- Troubleshooting connection issues
Key Guidance
Connection Modes:
| Mode | Architecture | Description |
|---|---|---|
| Standalone/Proxy | Standard or Cluster (proxy mode) | Connect via proxy node; supports all Redis commands including cross-slot multi-key |
| Cluster Direct | Cluster (direct mode) | Connect directly to data nodes; requires cluster-aware client; cross-slot multi-key commands not supported |
| TLS | Any (overlay) | Encrypt connections with TLS/SSL; supports both Proxy and Direct modes |
Authentication Format:
- Default account: password only
- Custom account:
<user>:<password> - redis-cli: use
REDISCLI_AUTHenvironment variable —export REDISCLI_AUTH='InstanceID:Password'
Supported Clients: Jedis, Lettuce, Redisson (Java); redis-py (Python); Predis, phpredis (PHP); StackExchange.Redis (.NET); go-redis (Go); node-redis (Node.js); Spring Data Redis
References
- references/connection-management/connect-standalone-or-proxy.md — Standalone/proxy connection examples in Java, Python, PHP, .NET, Go, Spring Data Redis
- references/connection-management/connect-cluster.md — Cluster connection examples (JedisCluster, RedisCluster, LettuceCluster, go-redis cluster, redis-cli)
- references/connection-management/connect-with-tls.md — TLS/SSL connection examples for all client types (Proxy + Direct)
---
8. Performance Monitoring
Intelligent performance monitoring and diagnostics via the Tair AI Assistant (DAS API).
When to Use
- Diagnosing slow queries or performance degradation
- Analyzing memory usage and identifying big keys / hotspot keys
- Tuning instance parameters and connection settings
- Monitoring instance health and resource utilization
Key Guidance
For intelligent diagnostics, install and use the alibabacloud-tair-ai-assistant skill:
npx skills add aliyun/alibabacloud-aiops-skills --skill alibabacloud-tair-ai-assistant --agent <your-agent-platform>The AI Assistant provides natural language based diagnostics covering: instance management, performance analysis, slow queries, memory analysis, big key / hotspot key detection, parameter tuning, and connection troubleshooting.
References
- references/performance-monitoring/perf-monitoring.md — Performance monitoring reference
- alibabacloud-tair-ai-assistant
---
9. Error Troubleshooting
Diagnose and resolve common Tair errors across authentication, connection, cluster, memory, proxy, Lua/transactions, and client-specific issues.
When to Use
- Encountering authentication or connection errors
- Resolving cluster-related errors (cross-slot, moved, read-only)
- Handling memory exhaustion or command errors
- Debugging client-specific issues (Jedis, Lettuce, Redisson, go-redis, etc.)
Key Guidance
Common Error Categories:
| Category | Example Errors | Typical Cause |
|---|---|---|
| Authentication | NOAUTH Authentication required, WRONGPASS | Password not provided, incorrect password, or Lettuce CLIENT SETINFO bug |
| Connection | ERR illegal address, max number of clients reached | Client IP not in whitelist, connection pool leak, DNS failure |
| Cluster | CROSSSLOT Keys in request don't hash to the same slot, MOVED | Multi-key command across slots, key moved to another node |
| Memory/Command | OOM command not allowed, WRONGTYPE, ERR unknown command | Memory exceeded, wrong data type, command not supported |
| Proxy Mode | client ip is not in whitelist, redis temporary failure | Proxy whitelist, sub-instance timeout, request queue overflow |
| Lua/Transaction | BUSY Redis is busy running a script, NOSCRIPT | Long-running Lua script, script SHA not in cache |
| Client-specific | Jedis Could not get a resource from the pool, Lettuce NOAUTH with correct password, go-redis cluster format panic | Pool exhaustion, version incompatibility, RESP2/RESP3 mismatch |
References
- references/error-troubleshooting/errors-troubleshooting.md — Complete error tables with causes and solutions for all error categories and client libraries
- Common errors and troubleshooting
---
10. Backup and Recovery
Configure backup policies, create manual backups, restore data from backups, and perform point-in-time recovery (PITR).
When to Use
- Configuring automatic backup policies
- Creating a manual backup before high-risk operations
- Restoring data from a backup set
- Performing point-in-time recovery (PITR) or key-filtered recovery
Key Guidance
Persistence Policies:
| Policy | Mechanism | Key Feature |
|---|---|---|
| RDB | Periodic snapshots | Small files, non-blocking backup |
| AOF | Logs all write operations | Fsync every second by default, AOF rewrite reduces disk usage |
| Tair-Binlog | Incremental AOF archiving (Enterprise DRAM only) | Prevents AOF rewrite degradation, enables PITR accurate to the second |
Key CLI Operations:
modify-backup-policy— Modify automatic backup schedulecreate-backup— Create a manual backupdescribe-backups— Query available backup setsrestore-instance— Restore from backup set or point-in-time- Full backup:
--backup-id "$BACKUP_ID" - PITR:
--restore-type 1 --restore-time "2024-01-15T10:30:00Z" - Key-filtered PITR: add
--filter-key "session:*,user:*"
⚠️ HIGH-RISK OPERATION — `restore-instance` overwrites current data and cannot be undone.
Before executing any restore:
1. Verify current write traffic — Check if the instance has active writes; notify the user if so
2. Create a latest backup — Run create-backup to preserve current data as a rollback point3. Confirm with the user — Explicitly inform that data will be overwritten and obtain confirmation
References
- references/backup-and-recovery/backup-recovery.md — Complete backup/recovery guide with CLI examples and data protection details
- Data backup and restoration policies
---
References Index
| Reference | Description | Scope |
|---|---|---|
| references/cli-installation-guide.md | Aliyun CLI installation and configuration guide | Cross-cutting |
| references/ram-policies.md | RAM permission policy document | Cross-cutting |
| references/acceptance-criteria.md | CLI command correctness standards | Cross-cutting (QA) |
| references/related-commands.md | Complete CLI command and parameter reference | Instance Creation |
| references/verification-method.md | Success verification steps | Instance Creation |
| references/architecture-selection/arch-selection.md | Architecture selection decision guide | Architecture Selection |
| references/architecture-selection/arch-compare-oss-redis.md | Tair vs Open Source Redis comparison | Architecture Selection |
| references/data-structure-design/data-structure-design.md | Detailed data structure use cases | Data Structure Design |
| references/instance-creation/connect-create-instance.md | End-to-end instance creation and connection guide | Instance Creation |
| references/connection-management/connect-standalone-or-proxy.md | Standalone/proxy connection examples | Connection Management |
| references/connection-management/connect-cluster.md | Cluster connection examples | Connection Management |
| references/connection-management/connect-with-tls.md | TLS connection examples (Proxy + Direct) | Connection Management |
| references/performance-monitoring/perf-monitoring.md | Performance monitoring and diagnostics | Performance Monitoring |
| references/error-troubleshooting/errors-troubleshooting.md | Complete error tables with causes and solutions | Error Troubleshooting |
| references/backup-and-recovery/backup-recovery.md | Backup and recovery strategies with CLI examples | Backup and Recovery |
Acceptance Criteria: alibabacloud-tair-devtoolset
Scenario: Create Tair Enterprise Edition Instance Purpose: Skill Test Acceptance Criteria
---
Correct CLI Command Patterns
1. Product — Product name must be r-kvstore
CORRECT
aliyun r-kvstore create-tair-instance ...INCORRECT
# Error: Incorrect product name
aliyun redis create-tair-instance ...
aliyun tair create-tair-instance ...
aliyun kvstore create-tair-instance ...2. Command — Must use plugin mode (lowercase with hyphens)
CORRECT
aliyun r-kvstore create-tair-instance ...
aliyun r-kvstore describe-instance-attribute ...
aliyun r-kvstore modify-security-ips ...
aliyun r-kvstore allocate-instance-public-connection ...
aliyun r-kvstore describe-db-instance-net-info ...INCORRECT
# Error: Using legacy API PascalCase format
aliyun r-kvstore CreateTairInstance ...
aliyun r-kvstore DescribeInstanceAttribute ...
aliyun r-kvstore ModifySecurityIps ...3. Parameters — Parameter names must use hyphen format
CORRECT
aliyun r-kvstore create-tair-instance \
--biz-region-id cn-hangzhou \
--instance-class tair.rdb.1g \
--instance-type tair_rdb \
--vpc-id vpc-bp1xxx \
--vswitch-id vsw-bp1xxx \
--password "YourPassword123!" \
--charge-type PostPaid \
--auto-pay true \
--shard-type MASTER_SLAVE \
--zone-id cn-hangzhou-h \
--instance-name my-tair-test \
--user-agent AlibabaCloud-Agent-SkillsINCORRECT
# Error: Using PascalCase parameter names
aliyun r-kvstore create-tair-instance \
--RegionId cn-hangzhou \
--InstanceClass tair.rdb.1g
# Error: Incorrect region parameter name (should be --biz-region-id)
aliyun r-kvstore create-tair-instance \
--region-id cn-hangzhou4. user-agent — Must be included in every aliyun command
CORRECT
aliyun r-kvstore describe-instance-attribute \
--instance-id r-bp1xxx \
--user-agent AlibabaCloud-Agent-SkillsINCORRECT
# Error: Missing --user-agent
aliyun r-kvstore describe-instance-attribute \
--instance-id r-bp1xxx5. InstanceType Enum Values
CORRECT
--instance-type tair_rdb # DRAM memory type
--instance-type tair_scm # Persistent memory type
--instance-type tair_essd # ESSD/SSD disk typeINCORRECT
--instance-type rdb # Error: Incomplete
--instance-type TAIR_RDB # Error: Uppercase
--instance-type redis # Error: Invalid enum6. ShardType Enum Values
CORRECT
--shard-type MASTER_SLAVE # Master-slave high availability
--shard-type STAND_ALONE # Single nodeINCORRECT
--shard-type master_slave # Error: Should be uppercase
--shard-type MasterSlave # Error: Incorrect format7. ChargeType Enum Values
CORRECT
--charge-type PostPaid # Pay-as-you-go
--charge-type PrePaid # SubscriptionINCORRECT
--charge-type postpaid # Error: Incorrect case
--charge-type PayAsYouGo # Error: Invalid enum---
Script Execution Patterns
8. Script Invocation
CORRECT
export VPC_ID="vpc-bp1xxx"
export VSWITCH_ID="vsw-bp1xxx"
bash scripts/create-and-connect-test.shINCORRECT
# Error: Required environment variables not set
bash scripts/create-and-connect-test.sh
# Error: Incorrect parameter passing method
bash scripts/create-and-connect-test.sh --vpc-id vpc-bp1xxxTair vs Open Source Redis Comparison
Tair (Redis OSS-compatible) is fully compatible with Redis open source protocols, providing enhanced enterprise features.
Tair vs Self-managed Redis
| Item | Tair | Self-managed Redis |
|---|---|---|
| Security | VPC isolation, whitelists, custom accounts, TLS encryption, TDE, audit logs | Self-managed network security, no built-in auth, requires third-party SSL |
| Backup | Point-in-time recovery (data flashback) | Full data restoration only |
| O&M | 10+ metric groups, 5s monitoring, alert rules, large key analysis | Complex third-party tools required |
| Scaling | Elastic scaling, instant creation | Hardware procurement, manual node management |
| HA | Single-zone HA, zone-disaster recovery, independent central module | Sentinel mode, higher cost, potential split-brain issues |
| Memory | 100% available (overhead handled by Alibaba Cloud) | 25-40% reserved for DR/O&M |
Tair Edition Selection Guide
| Series | Performance | Cost | Best For |
|---|---|---|---|
| Memory-optimized | 300% vs Redis OSS | ~117% | Performance-critical, mission-critical workloads |
| Persistent memory | 90% vs Redis OSS | ~70% | High persistence, cost-effective storage |
| Disk-based (ESSD/SSD) | 40-60% vs Redis OSS | 15-20% | Large storage, low access density, cost-primary |
| Redis Open-Source Edition | Baseline | 100% | Standard Redis use, migration scenarios |
Tair Enterprise vs Redis Open-Source Edition
| Feature | Tair Enterprise | Redis Open-Source |
|---|---|---|
| Extended data structures | exString, exHash, exZset, GIS, Bloom, Doc, TS, Cpc, Roaring, Search, Vector | Not supported |
| TDE (Transparent Data Encryption) | ✔️ | ❌ |
| Data flashback (PITR) | ✔️ | ❌ |
| Global Distributed Cache | ✔️ | ❌ |
| Proxy query cache | ✔️ | ❌ |
| Semi-synchronous mode | ✔️ | ❌ |
| Max connections per node | 30,000 | 10,000 |
| Single-key QPS | 450,000 | 140,000-160,000 |
When to Use
Use Tair Enterprise (Memory-optimized):
- Ultra-high performance required (3x throughput)
- Need extended data structures (Vector, Search, etc.)
- Enterprise security (TDE, data flashback)
Use Tair Enterprise (Persistent memory):
- Cost-effective with high data persistence
- Command-level persistence without data loss
Use Tair Enterprise (Disk-based):
- Large storage needs (hundreds of TB)
- Low access density, cost-primary scenarios
Use Redis Open-Source Edition:
- Standard Redis workloads
- Migration from self-managed Redis
- Cost-sensitive with baseline performance needs
References:
Architecture Selection
Choose the right Tair architecture based on data volume, throughput requirements, and read/write ratio.
Key Concepts
| Component | Description |
|---|---|
| Node | Smallest unit, runs Redis-compatible process |
| Shard | Group of nodes storing a subset of data |
| Master node | Handles write operations |
| Replica node | Copy of master, provides failover |
| Read-only node | Serves read traffic only (read/write splitting) |
| Proxy node | Routes requests to appropriate nodes |
Architecture Comparison
| Dimension | Standard | Cluster |
|---|---|---|
| Structure | One master + replicas | Multiple shards, each with master + replicas |
| Data partitioning | No (single shard) | Yes (distributed across shards) |
| Best for | Small data, stable QPS | Large data, high QPS, throughput-intensive |
| Read/write splitting | Supported | Supported |
Standard Architecture
Master-replica architecture where master handles all reads/writes, replica maintains real-time copy.
When to use:
- Data fits on single instance
- Stable query rate within single-node capacity
- Need persistent storage with high availability
Standard + Read/Write Splitting:
- Add proxy nodes + read-only nodes
- Proxy routes writes to master, distributes reads
- Use when: high QPS with read-heavy workload
Cluster Architecture
Data partitioned across multiple shards. Each shard uses master-replica for HA.
When to use:
- Large data volumes exceeding single-node capacity
- High QPS requirements
- Throughput-intensive workloads
Cluster + Read/Write Splitting:
- Each shard adds dedicated read-only nodes
- Use when: read traffic exceeds master node capacity per shard
Selection Decision Tree
Example:
Data volume > single-node capacity?
├── Yes → Cluster architecture
│ └── Read-heavy? → Enable read/write splitting
└── No → Standard architecture
└── Read-heavy? → Enable read/write splittingReference: Tair Product Architecture
Backup and Recovery
Tair provides RDB, AOF, and Tair-Binlog persistence policies to meet backup and restoration requirements in various scenarios.
Persistence Policies
| Policy | Mechanism | Characteristics |
|---|---|---|
| RDB | Snapshots of in-memory data at specified intervals | Small file size, easy to migrate, point-in-time backup. Tair optimizes persistence to achieve non-blocking backup without affecting client requests. |
| AOF | Logs all write operations (e.g., SET) | AOF_FSYNC_EVERYSEC by default — asynchronously writes commands to disk every second, minimizing performance impact. AOF rewrite reorganizes the file to reduce disk usage. |
| Tair-Binlog | Incremental AOF archiving (Tair Enterprise Edition DRAM-based only) | Prevents performance degradation from AOF rewrite. Saves each write operation with timestamp, enabling point-in-time recovery (PITR) accurate to the second. |
Backup
Example: Automatic backup policy
By default, Tair instances back up data automatically once a day. You can modify the policy via console or CLI.
# Modify automatic backup policy via aliyun CLI
aliyun r-kvstore modify-backup-policy \
--instance-id "$INSTANCE_ID" \
--preferred-backup-time "03:00Z-04:00Z" \
--preferred-backup-period "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Manual backup
Create a temporary backup at any time for data verification or before high-risk operations.
# Create a manual backup
aliyun r-kvstore create-backup \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Download backup files
Backup files are retained for 7 days by default. Download them for long-term retention due to regulatory or security requirements.
# Query available backup sets (start-time / end-time are REQUIRED, UTC format yyyy-MM-ddTHH:mmZ)
aliyun r-kvstore describe-backups \
--instance-id "$INSTANCE_ID" \
--start-time "2024-01-01T00:00Z" \
--end-time "2024-01-31T23:59Z" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skills
# Download the backup file from the BackupSetDownloadURL field in the responseRecovery
⚠️ HIGH-RISK OPERATION — Data will be overwritten
restore-instance overwrites the current instance data and cannot be undone. Before executing any restore operation, you MUST complete the following pre-checks:>
1. Verify current write traffic — Check whether the instance has active write traffic (monitor QPS in console). If yes, notify the user and confirm before proceeding.
2. Create a latest backup — Run aliyun r-kvstore create-backup to create a backup of the current data before restoring, so you can roll back if the restore goes wrong.3. Confirm with the user — Explicitly inform the user that the restore will overwrite current data and obtain confirmation before execution.
Example: Restore from a backup set
Restore data from a specified backup set to the current instance. For non-DRAM instances, it is recommended to create a new instance from the backup set instead.
# [Pre-check] Create a backup of current data before restoring
aliyun r-kvstore create-backup \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skills
# Wait for backup to complete, then proceed with restore
aliyun r-kvstore restore-instance \
--instance-id "$INSTANCE_ID" \
--backup-id "$BACKUP_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Point-in-time recovery (PITR) via data flashback
Restore data to a specified point in time accurate to the second. Available only for Tair Enterprise Edition DRAM-based instances with data flashback enabled. Use RestoreType=1 with RestoreTime in UTC format.
# [Pre-check] Create a backup of current data before restoring
aliyun r-kvstore create-backup \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skills
# Restore instance data to a specific point in time
aliyun r-kvstore restore-instance \
--instance-id "$INSTANCE_ID" \
--restore-type 1 \
--restore-time "2024-01-15T10:30:00Z" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsYou can also restore only specific keys using FilterKey with regex patterns:
# [Pre-check] Create a backup of current data before restoring
aliyun r-kvstore create-backup \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skills
# Restore only specific keys matching the regex pattern
aliyun r-kvstore restore-instance \
--instance-id "$INSTANCE_ID" \
--restore-type 1 \
--restore-time "2024-01-15T10:30:00Z" \
--filter-key "session:*,user:00000007198*" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsBackup Data Protection
| Protection | Description |
|---|---|
| Tamper resistance | RDB and Tair-Binlog data is stored in OSS with WORM (Write Once Read Many) feature |
| Manual deletion | Only manual backup data can be deleted; automatic backup data cannot be deleted |
| Automatic expiration | At least one automatic backup per week, retained for at least 7 days — automatic backup data cannot be completely deleted |
Reference: Data backup and restoration policies and solutions
Aliyun CLI Installation & Configuration Guide
Complete guide for installing and configuring Aliyun CLI.
Aliyun CLI 3.3.3+: Supports installing and using all published Alibaba Cloud product plugins. Make sure to upgrade to 3.3.3 or later for full plugin ecosystem coverage.
Installation
macOS
Using Homebrew (Recommended)
brew install aliyun-cli
# Upgrade to latest
brew upgrade aliyun-cli
# Verify version (>= 3.3.3)
aliyun versionUsing Binary
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-macosx-latest-amd64.tgz
# Extract
tar -xzf aliyun-cli-macosx-latest-amd64.tgz
# Move to PATH
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionLinux
Debian/Ubuntu
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-amd64.tgz
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionCentOS/RHEL
# Download
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-amd64.tgz
sudo mv aliyun /usr/local/bin/
# Verify
aliyun versionARM64 Architecture
# Download ARM64 version
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-arm64.tgz
# Extract and install
tar -xzf aliyun-cli-linux-latest-arm64.tgz
sudo mv aliyun /usr/local/bin/Windows
Using Binary 1. Download from: https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip 2. Extract the ZIP file 3. Add the directory to your PATH environment variable 4. Open new Command Prompt or PowerShell 5. Verify: aliyun version
Using PowerShell
# Download
Invoke-WebRequest -Uri "https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip" -OutFile "aliyun-cli.zip"
# Extract
Expand-Archive -Path aliyun-cli.zip -DestinationPath C:\aliyun-cli
# Add to PATH (requires admin privileges)
$env:Path += ";C:\aliyun-cli"
[Environment]::SetEnvironmentVariable("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)
# Verify
aliyun versionConfiguration
Quick Start
aliyun configure set \
--mode AK \
--access-key-id <your-access-key-id> \
--access-key-secret <your-access-key-secret> \
--region cn-hangzhouAll aliyun configure commands support non-interactive flags, which is the recommended approach — it works in scripts, CI/CD pipelines, and agent-driven automation without hanging on stdin prompts.
Where to Get Access Keys
1. Log in to Aliyun Console: https://ram.console.aliyun.com/ 2. Navigate to: AccessKey Management 3. Create a new AccessKey pair 4. Save the secret immediately — it's only shown once
Configuration Modes
Aliyun CLI supports 6 authentication modes. All examples below use non-interactive flags.
1. AK Mode (Access Key)
Most common mode for personal accounts and scripts.
aliyun configure set \
--mode AK \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--region cn-hangzhouConfiguration is stored in ~/.aliyun/config.json:
{
"current": "default",
"profiles": [
{
"name": "default",
"mode": "AK",
"access_key_id": "LTAI5tXXXXXXXX",
"access_key_secret": "8dXXXXXXXXXXXXXXXXXXXXXXXX",
"region_id": "cn-hangzhou",
"output_format": "json",
"language": "en"
}
]
}2. StsToken Mode (Temporary Credentials)
For short-lived access (tokens expire in 1-12 hours).
aliyun configure set \
--mode StsToken \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--sts-token v1.0:XXXXXXXXXXXXXXXX \
--region cn-hangzhouUse cases: CI/CD pipelines, temporary access for external contractors, cross-account access.
3. RamRoleArn Mode (Assume RAM Role)
Assume a RAM role for elevated or cross-account access.
aliyun configure set \
--mode RamRoleArn \
--access-key-id LTAI5tXXXXXXXX \
--access-key-secret 8dXXXXXXXXXXXXXXXXXXXXXXXX \
--ram-role-arn acs:ram::123456789012:role/AdminRole \
--role-session-name my-session \
--region cn-hangzhouUse cases: cross-account resource access, temporary elevated privileges, role-based access control.
4. EcsRamRole Mode (ECS Instance RAM Role)
Use the RAM role attached to an ECS instance — no credentials needed.
aliyun configure set \
--mode EcsRamRole \
--ram-role-name MyEcsRole \
--region cn-hangzhouRequirements: must be running on an ECS instance with a RAM role attached.
Use cases: scripts and automation running on ECS instances.
5. RsaKeyPair Mode (RSA Key Pair)
Use RSA key pair for authentication (generate key pair in Aliyun Console first).
aliyun configure set \
--mode RsaKeyPair \
--private-key /path/to/private-key.pem \
--key-pair-name my-key-pair \
--region cn-hangzhou6. RamRoleArnWithEcs Mode (ECS + RAM Role)
Combine ECS instance role with RAM role assumption for cross-account access from ECS.
aliyun configure set \
--mode RamRoleArnWithEcs \
--ram-role-name MyEcsRole \
--ram-role-arn acs:ram::123456789012:role/TargetRole \
--role-session-name my-session \
--region cn-hangzhouEnvironment Variables
Highest priority - overrides config file
Access Key Mode
export ALIBABA_CLOUD_ACCESS_KEY_ID=your_access_key_id
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_access_key_secret
export ALIBABA_CLOUD_REGION_ID=cn-hangzhouSTS Token Mode
export ALIBABA_CLOUD_ACCESS_KEY_ID=your_access_key_id
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_access_key_secret
export ALIBABA_CLOUD_SECURITY_TOKEN=your_sts_token
export ALIBABA_CLOUD_REGION_ID=cn-hangzhouECS RAM Role Mode
export ALIBABA_CLOUD_ECS_METADATA=role_nameUse Case:
- CI/CD pipelines
- Docker containers
- Temporary credential override
Managing Multiple Profiles
Create Named Profiles
aliyun configure set --profile projectA \
--mode AK \
--access-key-id LTAI5tAAAAAAAA \
--access-key-secret 8dAAAAAAAAAAAAAAAAAAAAAAAA \
--region cn-hangzhou
aliyun configure set --profile projectB \
--mode AK \
--access-key-id LTAI5tBBBBBBBB \
--access-key-secret 8dBBBBBBBBBBBBBBBBBBBBBBBB \
--region cn-shanghaiUse Specific Profile
aliyun ecs describe-instances --profile projectA
export ALIBABA_CLOUD_PROFILE=projectA
aliyun ecs describe-instances # Uses projectAList and Switch Profiles
aliyun configure list # List all profiles
aliyun configure set --current projectA # Switch default profileCredential Priority
Credentials are loaded in this order (first found wins):
1. Command-line flag: --profile <name> 2. Environment variable: ALIBABA_CLOUD_PROFILE 3. Environment credentials: ALIBABA_CLOUD_ACCESS_KEY_ID, etc. 4. Configuration file: ~/.aliyun/config.json (current profile) 5. ECS Instance RAM Role: If running on ECS with attached role
Verification
Test Authentication
# Basic test - list regions
aliyun ecs describe-regions
# Expected output: JSON array of regionsIf successful, you'll see:
{
"Regions": {
"Region": [
{
"RegionId": "cn-hangzhou",
"RegionEndpoint": "ecs.cn-hangzhou.aliyuncs.com",
"LocalName": "China East 1 (Hangzhou)"
},
...
]
},
"RequestId": "..."
}If failed, you'll see error messages:
InvalidAccessKeyId.NotFound- Wrong Access Key IDSignatureDoesNotMatch- Wrong Access Key SecretInvalidSecurityToken.Expired- STS token expired (for StsToken mode)Forbidden.RAM- Insufficient permissions
Debug Configuration
# Show current configuration
aliyun configure get
# Test with debug logging
aliyun ecs describe-regions --log-level=debug
# Check credential provider
aliyun configure get modeSecurity Best Practices
1. Use RAM Users (Not Root Account)
❌ Don't: Use Aliyun root account credentials ✅ Do: Create RAM users with specific permissions
# Create RAM user in console
# Attach only necessary policies
# Use RAM user's access keys2. Principle of Least Privilege
Grant only the minimum permissions needed:
# Example: Read-only ECS access
# Attach policy: AliyunECSReadOnlyAccess3. Rotate Access Keys Regularly
# Create new access key in RAM Console, then update configuration
aliyun configure set --access-key-id NEW_KEY --access-key-secret NEW_SECRET
# Delete old access key from console4. Use STS Tokens for Temporary Access
aliyun configure set --mode StsToken \
--access-key-id XXXX --access-key-secret XXXX \
--sts-token XXXX --region cn-hangzhou5. Use ECS RAM Roles When Possible
aliyun configure set --mode EcsRamRole --ram-role-name MyRole --region cn-hangzhou6. Never Commit Credentials
# Add to .gitignore
echo "~/.aliyun/config.json" >> .gitignore
# Use environment variables in CI/CD instead7. Secure Config File
# Restrict permissions
chmod 600 ~/.aliyun/config.jsonTroubleshooting
Issue: Command Not Found
# Check installation
which aliyun
# Check PATH
echo $PATH
# Reinstall or add to PATHIssue: Authentication Failed
# Verify configuration
aliyun configure get
# Test with debug
aliyun ecs describe-regions --log-level=debug
# Check credentials in console
# Verify access key is activeIssue: Permission Denied
# Error: Forbidden.RAM
# Check RAM user permissions
# Attach necessary policies in RAM console
# Example: AliyunECSFullAccess for ECS operationsIssue: STS Token Expired
# Error: InvalidSecurityToken.Expired
# Reconfigure with new token
aliyun configure set --mode StsToken \
--access-key-id XXXX --access-key-secret XXXX \
--sts-token NEW_TOKEN --region cn-hangzhouIssue: Wrong Region
# Some resources may not exist in the specified region
# Check available regions
aliyun ecs describe-regions
# Update default region
aliyun configure set region cn-shanghaiAdvanced Configuration
Custom Endpoint
# Use custom or private endpoint
export ALIBABA_CLOUD_ECS_ENDPOINT=ecs-vpc.cn-hangzhou.aliyuncs.comProxy Settings
# HTTP proxy
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
# No proxy for specific domains
export NO_PROXY=localhost,127.0.0.1,.aliyuncs.comTimeout Settings
# Connection timeout (default: 10s)
export ALIBABA_CLOUD_CONNECT_TIMEOUT=30
# Read timeout (default: 10s)
export ALIBABA_CLOUD_READ_TIMEOUT=30Next Steps
After installation and configuration:
1. Install plugins for services you need (v3.3.3+ supports all published product plugins):
aliyun plugin install --names ecs vpc rds
# List all available plugins
aliyun plugin list-remote2. Explore commands:
aliyun ecs --help
aliyun fc --help3. Read documentation:
- Command Syntax Guide
- Global Flags Reference
- Common Scenarios
References
- Official Documentation: https://help.aliyun.com/zh/cli/
- RAM Console: https://ram.console.aliyun.com/
- Access Key Management: https://ram.console.aliyun.com/manage/ak
- Plugin Repository: https://github.com/aliyun/aliyun-cli
Connect Cluster
Connect to Tair cluster architecture instances using direct connection mode (private endpoint) with Redis Cluster protocol compatible clients.
Client Examples
Jedis (Java):
<!-- Maven dependency -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>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: Number of clients × MaxTotal < Max connections per shard
config.setMaxTotal(30);
config.setMaxIdle(20);
config.setMinIdle(15);
// Specify the private endpoint allocated to the cluster instance
String host = "r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com";
int port = 6379;
// Specify the password 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(); // Destroy resources when application exits
}
}redis-py (Python):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pip install redis
from redis.cluster import RedisCluster
# Replace the values of the host and port parameters with the endpoint and port
host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com'
port = 6379
# Replace the values of the user and pwd parameters with the username and password
user = 'testaccount'
pwd = 'Rp829dlwa'
rc = RedisCluster(host=host, port=port, username=user, password=pwd)
# You can perform operations after the connection is established
rc.set('foo', 'bar')
print(rc.get('foo'))PhpRedis (PHP):
// Install: pecl install redis
<?php
// Specify the private endpoint and port number
$array = ['r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379'];
// Specify the password 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;
?>Spring Data Redis (Java):
<!-- Maven 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>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
</project>// Spring Data Redis Cluster Configuration
@Configuration
public class RedisClusterConfig {
@Bean
public RedisClusterConfiguration redisClusterConfiguration() {
// Specify the private endpoint
RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(
Arrays.asList("r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379")
);
// Password format: account:password
clusterConfig.setPassword("testaccount:Rp829dlwa");
return clusterConfig;
}
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(30);
poolConfig.setMaxIdle(20);
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnReturn(false);
JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
.usePooling().poolConfig(poolConfig).build();
return new JedisConnectionFactory(redisClusterConfiguration(), clientConfig);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}ioredis (Node.js):
// npm install ioredis
const Redis = require('ioredis');
// Connect to cluster using private endpoint
const cluster = new Redis.Cluster([
{
host: 'r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com',
port: 6379
}
], {
redisOptions: {
password: 'testaccount:Rp829dlwa' // account:password format
}
});
cluster.set('foo', 'bar', (err, result) => {
if (err) {
console.error(err);
return;
}
console.log('Set result:', result);
});
cluster.get('foo', (err, result) => {
if (err) {
console.error(err);
return;
}
console.log('Get result:', result);
});go-redis (Go):
// go get github.com/redis/go-redis/v9
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
// Connect to cluster using private endpoint
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"r-bp1xxxxxxxxxxxx.redis.rds.aliyuncs.com:6379"},
Password: "testaccount:Rp829dlwa", // account:password format
})
// Set operation
err := rdb.Set(ctx, "foo", "bar", 0).Err()
if err != nil {
panic(err)
}
// Get operation
val, err := rdb.Get(ctx, "foo").Result()
if err != nil {
panic(err)
}
fmt.Println("foo =", val)
}redis-cli:
# Must add -c parameter for cluster connection
./redis-cli -h r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com -p 6379 -c
# Verify password
AUTH testaccount:Rp829dlwaReference: Use direct connection mode to connect to cluster instance
Connect Standalone or Proxy
Connect to Tair standard architecture or cluster/proxy mode instances using Redis-compatible clients.
Client Examples
Jedis (Java):
<!-- Maven dependency -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>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();
// The maximum number of idle connections
config.setMaxIdle(200);
// The maximum number of connections
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
// Replace the values of the host and password parameters with the endpoint and password of the instance
String host = "r-bp1s1bt2tlq3p1****pd.redis.rds.aliyuncs.com";
// For a default account, enter the password directly
// For a newly created account, the password must be in the Account:Password format
String password = "r-bp1s1bt2tlq3p1****:Database123";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
try {
jedis = pool.getResource();
// Perform operations
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) {
// Handle a timeout or other exceptions
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
// When the application exits, call this method to release resources
pool.destroy();
}
}redis-py (Python):
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# pip install redis
import redis
# Replace the values of the host and port parameters with the endpoint and port of the instance
host = 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com'
port = 6379
# Replace the value of the pwd parameter with the password of the instance
# For a default account, you can directly enter the password
# For a newly created account, the password must be in the Account:Password format
pwd = 'testaccount:Rp829dlwa'
r = redis.Redis(host=host, port=port, password=pwd)
# After the connection is established, you can perform database operations
r.set('foo', 'bar')
print(r.get('foo'))PhpRedis (PHP):
// Install: pecl install redis
<?php
/* Replace the values of the host and port parameters with the endpoint and port of the instance */
$host = "r-bp10noxlhcoim2****.redis.rds.aliyuncs.com";
$port = 6379;
/* Replace the values of the user and pwd parameters with the account and password of the instance */
$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());
}
/* After the authentication is complete, you can perform database operations */
if ($redis->set("foo", "bar") == false) {
die($redis->getLastError());
}
$value = $redis->get("foo");
echo $value;
?>Spring Data Redis (Java):
<!-- Maven 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>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- Use Lettuce 6.3.0+ to prevent blackhole issues -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0.RELEASE</version>
</dependency>
</dependencies>
</project>// Spring Data Redis With Jedis
@Configuration
public class RedisConfig {
@Bean
JedisConnectionFactory redisConnectionFactory() {
// Connection address (hostName) and port obtained from instance details page
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(
"r-8vbwds91ie1rdl****.redis.zhangbei.rds.aliyuncs.com", 6379);
// Password format: account:password
config.setPassword(RedisPassword.of("testaccount:Rp829dlwa"));
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// Max connections, cannot exceed instance limit
jedisPoolConfig.setMaxTotal(30);
// Max idle connections
jedisPoolConfig.setMaxIdle(20);
// Disable testOnBorrow/Return to avoid extra PING
jedisPoolConfig.setTestOnBorrow(false);
jedisPoolConfig.setTestOnReturn(false);
JedisClientConfiguration jedisClientConfiguration = JedisClientConfiguration.builder()
.usePooling().poolConfig(jedisPoolConfig).build();
return new JedisConnectionFactory(config, jedisClientConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}node-redis (Node.js):
// npm install redis
const redis = require('redis');
const client = redis.createClient({
socket: {
host: 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com',
port: 6379
},
// For default account, enter password directly
// For custom account, use 'account:password' format
password: 'testaccount:Rp829dlwa'
});
client.on('error', (err) => console.log('Redis Client Error', err));
async function main() {
await client.connect();
await client.set('foo', 'bar');
const value = await client.get('foo');
console.log(value);
await client.disconnect();
}
main();ioredis (Node.js):
// npm install ioredis
const Redis = require('ioredis');
const redis = new Redis({
host: 'r-bp10noxlhcoim2****.redis.rds.aliyuncs.com',
port: 6379,
// For default account, enter password directly
// For custom account, use 'account:password' format
password: 'testaccount:Rp829dlwa',
db: 0
});
redis.set('foo', 'bar', (err, result) => {
if (err) {
console.error(err);
return;
}
console.log('Set result:', result);
});
redis.get('foo', (err, result) => {
if (err) {
console.error(err);
return;
}
console.log('Get result:', result);
});go-redis (Go):
// go get github.com/redis/go-redis/v9
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "r-bp10noxlhcoim2****.redis.rds.aliyuncs.com:6379",
// For default account, enter password directly
// For custom account, use 'account:password' format
Password: "testaccount:Rp829dlwa",
DB: 0,
})
// Set operation
err := rdb.Set(ctx, "foo", "bar", 0).Err()
if err != nil {
panic(err)
}
// Get operation
val, err := rdb.Get(ctx, "foo").Result()
if err != nil {
panic(err)
}
fmt.Println("foo =", val)
}Reference: Connect to Tair using a client
Connect With TLS
Connect to Tair instances with TLS (SSL) encryption to secure data in transit. Download the CA certificate (ApsaraDB-CA-Chain.pem or .jks) from the TLS encryption page.
Proxy Connection Mode
Use these examples for standard architecture, cluster architecture with proxy mode, or read/write splitting architecture.
Jedis (Java):
<!-- Maven dependency -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisSSLTest {
private static SSLSocketFactory createTrustStoreSSLSocketFactory(String jksFile) throws Exception {
KeyStore trustStore = KeyStore.getInstance("jks");
InputStream inputStream = null;
try {
inputStream = new FileInputStream(jksFile);
trustStore.load(inputStream, null);
} finally {
inputStream.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
}
public static void main(String[] args) throws Exception {
// ApsaraDB-CA-Chain.jks is the certificate file name
final SSLSocketFactory sslSocketFactory = createTrustStoreSSLSocketFactory("ApsaraDB-CA-Chain.jks");
// Configure the connection pool with the instance endpoint, port, timeout, and password
JedisPool pool = new JedisPool(new GenericObjectPoolConfig(),
"r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com",
6379, 2000, "redistest:Pas***23", 0, true, sslSocketFactory, null, null);
try (Jedis jedis = pool.getResource()) {
jedis.set("key", "value");
System.out.println(jedis.get("key"));
}
}
}redis-py (Python):
#!/bin/python
# pip install redis
import redis
# Connection pool approach
# ApsaraDB-CA-Chain.pem is the certificate file name
pool = redis.ConnectionPool(
connection_class=redis.connection.SSLConnection,
max_connections=100,
host="r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com",
port=6379,
password="redistest:Pas***23",
ssl_cert_reqs=True,
ssl_ca_certs="ApsaraDB-CA-Chain.pem"
)
client = redis.Redis(connection_pool=pool)
client.set("hi", "redis")
print(client.get("hi"))#!/bin/python
# pip install redis
import redis
# Standard connection approach
client = redis.Redis(
host="r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com",
port=6379,
password="redistest:Test1234",
ssl=True,
ssl_cert_reqs="required",
ssl_ca_certs="ApsaraDB-CA-Chain.pem"
)
client.set("hello", "world")
print(client.get("hello"))Predis (PHP):
// composer require predis/predis
<?php
require __DIR__.'/predis/autoload.php';
/* ApsaraDB-CA-Chain.pem is the certificate file name
Replace host, port, and password with your instance values */
$client = new Predis\Client([
'scheme' => 'tls',
'host' => 'r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com',
'port' => 6379,
'password' => 'redistest:Pas***23',
'ssl' => ['cafile' => 'ApsaraDB-CA-Chain.pem', 'verify_peer' => true],
]);
$client->set("hello", "world");
print $client->get("hello")."\n";
?>StackExchange.Redis (C#):
// Install-Package StackExchange.Redis
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using StackExchange.Redis;
namespace SSLTest
{
class Program
{
private static bool CheckServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
var ca = new X509Certificate2(
"/your path/ApsaraDB-CA-Chain/ApsaraDB-CA-Chain.pem");
return chain.ChainElements
.Cast<X509ChainElement>()
.Any(x => x.Certificate.Thumbprint == ca.Thumbprint);
}
static void Main(string[] args)
{
// ApsaraDB-CA-Chain.pem is the certificate file name
ConfigurationOptions config = new ConfigurationOptions()
{
EndPoints = {"r-bp10q23zyfriodu****.redis.rds.aliyuncs.com:6379"},
Password = "redistest:Pas***23",
Ssl = true,
};
config.CertificateValidation += CheckServerCertificate;
using (var conn = ConnectionMultiplexer.Connect(config))
{
Console.WriteLine("connected");
var db = conn.GetDatabase();
db.StringSet("hello", "world");
Console.WriteLine(db.StringGet("hello"));
}
}
}
}Spring Data Redis (Java):
// Spring Data Redis 2.7.12 or later
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
// Store TLS certificate configuration in a properties file for production use
String host = "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com";
int port = 6379;
String password = "Pas***23";
String trustStoreFilePath = "/path/to/ApsaraDB-CA-Chain.jks";
ClientOptions clientOptions = ClientOptions.builder().sslOptions(
SslOptions.builder().jdkSslProvider().truststore(new File(trustStoreFilePath)).build()).build();
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(password);
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.clientOptions(clientOptions)
.useSsl().build();
return new LettuceConnectionFactory(config, lettuceClientConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}Lettuce (Java):
// Lettuce 6.2.4.RELEASE or later
public class SSLExample {
public static void main(String[] args) throws Exception {
String host = "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com";
int port = 6379;
String password = "Pas***23";
String trustStoreFilePath = "/path/to/ApsaraDB-CA-Chain.jks";
RedisURI uri = RedisURI.builder()
.withHost(host)
.withPort(port)
.withPassword(password.toCharArray())
.withSsl(true).build();
SslOptions sslOptions = SslOptions.builder()
.jdkSslProvider()
.truststore(new File(trustStoreFilePath)).build();
ClientOptions clientOptions = ClientOptions.builder()
.sslOptions(sslOptions).build();
RedisClient client = RedisClient.create(uri);
client.setOptions(clientOptions);
RedisCommands<String, String> sync = client.connect().sync();
System.out.println(sync.set("key", "value"));
System.out.println(sync.get("key"));
}
}go-redis (Go):
// go get github.com/redis/go-redis/v9
package main
import (
"context"
"fmt"
"io/ioutil"
"crypto/tls"
"crypto/x509"
"github.com/redis/go-redis/v9"
)
var ctx = context.Background()
func main() {
caCert, err := ioutil.ReadFile("/root/ApsaraDB-CA-Chain.pem")
if err != nil {
fmt.Println("Error loading CA certificate:", err)
return
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
RootCAs: caCertPool,
InsecureSkipVerify: true, // Skip hostname verification, CA still validated
}
rdb := redis.NewClient(&redis.Options{
Addr: "r-bp1zxszhcgatnx****.redis.rds.aliyuncs.com:6379",
Password: "redistest:Pas***23",
TLSConfig: tlsConfig,
})
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)
}redis-cli:
# Build redis-cli with TLS support
sudo yum -y install openssl-devel gcc
wget --timeout=60 https://download.redis.io/releases/redis-7.2.0.tar.gz
tar xzf redis-7.2.0.tar.gz
cd redis-7.2.0 && make BUILD_TLS=yes
# Connect with TLS, specifying the CA certificate path
./src/redis-cli -h r-bp14joyeihew30****.redis.rds.aliyuncs.com -p 6379 --tls --cacert ./ApsaraDB-CA-Chain.pem
# Authenticate
AUTH passwordDirect Connection Mode
Use these examples for cluster architecture with direct connection mode enabled.
JedisCluster (Java):
<!-- Maven dependency -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.HashSet;
import java.util.Set;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import redis.clients.jedis.ConnectionPoolConfig;
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class JedisClusterTSL {
private static final int DEFAULT_TIMEOUT = 2000;
private static final int DEFAULT_REDIRECTIONS = 5;
private static final ConnectionPoolConfig jedisPoolConfig = new ConnectionPoolConfig();
private static SSLSocketFactory createTrustStoreSSLSocketFactory(String jksFile) throws Exception {
KeyStore trustStore = KeyStore.getInstance("jks");
InputStream inputStream = null;
try {
inputStream = new FileInputStream(jksFile);
trustStore.load(inputStream, null);
} finally {
inputStream.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
}
public static void main(String args[]) throws Exception {
// In direct connection mode, keep (business machines × MaxTotal) below the per-shard connection limit
jedisPoolConfig.setMaxTotal(30);
jedisPoolConfig.setMaxIdle(30);
jedisPoolConfig.setMinIdle(15);
int port = 6379;
String host = "r-2zee50zxi5iiq****.redis.rds-aliyun.rds.aliyuncs.com";
String user = "default";
String password = "Pas***23";
final SSLSocketFactory sslSocketFactory = createTrustStoreSSLSocketFactory("/root/ApsaraDB-CA-Chain.jks");
DefaultJedisClientConfig jedisClientConfig = DefaultJedisClientConfig.builder()
.connectionTimeoutMillis(DEFAULT_TIMEOUT)
.socketTimeoutMillis(DEFAULT_TIMEOUT)
.user(user).password(password)
.ssl(true)
.sslSocketFactory(sslSocketFactory).build();
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort(host, port));
JedisCluster jc = new JedisCluster(jedisClusterNode, jedisClientConfig, DEFAULT_REDIRECTIONS, jedisPoolConfig);
System.out.println(jc.set("key", "value"));
System.out.println(jc.get("key"));
jc.close(); // Call when the application exits to release resources
}
}redis-py Cluster (Python):
#!/usr/bin/env python
# pip install redis
from redis.cluster import RedisCluster
# Replace host and port with your instance endpoint and port
host = 'r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com'
port = 6379
# Replace user and pwd with your instance account and password
user = 'default'
pwd = 'Pas***23'
rc = RedisCluster(host=host, port=port, username=user, password=pwd,
ssl=True, ssl_ca_certs="/root/ApsaraDB-CA-Chain.pem")
rc.set('foo', 'bar')
print(rc.get('foo'))phpredis Cluster (PHP):
// pecl install redis
<?php
// Direct connection endpoint and port
$array = ['r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com:6379'];
// Connection password
$pwd = "Pas***23";
// TLS settings
$tls = ["verify_peer" => false, "verify_peer_name" => false];
// Connect to the cluster
$obj_cluster = new RedisCluster(NULL, $array, 1.5, 1.5, true, $pwd, $tls);
var_dump($obj_cluster);
if ($obj_cluster->set("foo", "bar") == false) {
die($obj_cluster->getLastError());
}
$value = $obj_cluster->get("foo");
echo $value;
echo "\n";
?>StackExchange.Redis Cluster (C#):
// Install-Package StackExchange.Redis
using StackExchange.Redis;
using System;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace TairClient
{
class Program
{
static void Main()
{
const string Host = "r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com";
const int Port = 6379;
Console.WriteLine("connecting...");
var config = new ConfigurationOptions
{
EndPoints = { { Host, Port } },
Ssl = true,
Password = "Pas***23",
};
config.CertificateValidation += (sender, cert, chain, errors) =>
{
if (errors == SslPolicyErrors.RemoteCertificateChainErrors ||
errors == SslPolicyErrors.RemoteCertificateNameMismatch)
{
return true;
}
var caCert = LoadCertificateFromPem("/root/ApsaraDB-CA-Chain.pem");
var isCertIssuedByTrustedCA = chain.ChainElements
.Cast<X509ChainElement>()
.Any(x => x.Certificate.Thumbprint.Equals(
caCert.Thumbprint, StringComparison.OrdinalIgnoreCase));
return isCertIssuedByTrustedCA;
};
using (var conn = ConnectionMultiplexer.Connect(config))
{
Console.WriteLine("connected");
var db = conn.GetDatabase();
db.StringSet("hello", "world");
Console.WriteLine(db.StringGet("hello")); // world
}
}
private static X509Certificate2 LoadCertificateFromPem(string pemFilePath)
{
X509Certificate2 cert = X509Certificate2.CreateFromPem(File.ReadAllText(pemFilePath));
return cert;
}
}
}Spring Data Redis Cluster - Jedis (Java):
// Spring Data Redis 2.7.5 or later
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
public class RedisConfigJedis {
private static SSLSocketFactory createTrustStoreSSLSocketFactory(String jksFile) throws Exception {
KeyStore trustStore = KeyStore.getInstance("jks");
InputStream inputStream = null;
try {
inputStream = new FileInputStream(jksFile);
trustStore.load(inputStream, null);
} finally {
inputStream.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
}
@Bean
public RedisConnectionFactory redisConnectionFactory() throws Exception {
String host = "r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com:6379";
String user = "default";
String password = "Pas***23";
String trustStoreFilePath = "/root/ApsaraDB-CA-Chain.jks";
List<String> clusterNodes = Arrays.asList(host);
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(clusterNodes);
redisClusterConfiguration.setUsername(user);
redisClusterConfiguration.setPassword(password);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// In direct connection mode, keep (business machines × MaxTotal) below the per-shard connection limit
jedisPoolConfig.setMaxTotal(30);
jedisPoolConfig.setMaxIdle(20);
jedisPoolConfig.setMinIdle(20);
final SSLSocketFactory sslSocketFactory = createTrustStoreSSLSocketFactory(trustStoreFilePath);
JedisClientConfiguration jedisClientConfiguration = JedisClientConfiguration.builder()
.useSsl().sslSocketFactory(sslSocketFactory)
.and().usePooling().poolConfig(jedisPoolConfig).build();
return new JedisConnectionFactory(redisClusterConfiguration, jedisClientConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}Spring Data Redis Cluster - Lettuce (Java):
// Spring Data Redis 2.7.5 or later
import java.io.File;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.SslOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
String host = "r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com";
int port = 6379;
String user = "default";
String password = "Pas***23";
String trustStoreFilePath = "/root/ApsaraDB-CA-Chain.jks";
ClientOptions clientOptions = ClientOptions.builder().sslOptions(
SslOptions.builder().jdkSslProvider().truststore(new File(trustStoreFilePath)).build()).build();
RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
clusterConfiguration.clusterNode(host, port);
clusterConfiguration.setUsername(user);
clusterConfiguration.setPassword(password);
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
.clientOptions(clientOptions)
.useSsl()
.disablePeerVerification()
.build();
return new LettuceConnectionFactory(clusterConfiguration, lettuceClientConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}Lettuce Cluster (Java):
// Lettuce 6.3.0.RELEASE or later
import java.io.File;
import java.time.Duration;
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.SslOptions;
import io.lettuce.core.SslVerifyMode;
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;
public class SSLClusterExample {
/**
* TCP keepalive settings:
* TCP_KEEPIDLE = 30s, TCP_KEEPINTVL = 10s, TCP_KEEPCNT = 3
*/
private static final int TCP_KEEPALIVE_IDLE = 30;
/**
* TCP_USER_TIMEOUT prevents Lettuce from hanging indefinitely on broken connections.
* See: 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 {
String host = "r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com";
int port = 6379;
String password = "Pas***23";
String trustStoreFilePath = "/root/ApsaraDB-CA-Chain.jks";
RedisURI uri = RedisURI.builder()
.withHost(host)
.withPort(port)
.withPassword(password.toCharArray())
.withSsl(true)
// Direct cluster connections require CA-only verification; FULL mode is not supported.
.withVerifyPeer(SslVerifyMode.CA)
.build();
SslOptions sslOptions = SslOptions.builder()
.jdkSslProvider()
.truststore(new File(trustStoreFilePath)).build();
ClusterTopologyRefreshOptions refreshOptions = ClusterTopologyRefreshOptions.builder()
.enablePeriodicRefresh(Duration.ofSeconds(15))
.dynamicRefreshSources(false)
.enableAllAdaptiveRefreshTriggers()
.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(15)).build();
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();
RedisClusterClient redisClient = RedisClusterClient.create(uri);
redisClient.setOptions(ClusterClientOptions.builder()
.socketOptions(socketOptions)
.sslOptions(sslOptions)
.validateClusterNodeMembership(false)
.topologyRefreshOptions(refreshOptions).build());
StatefulRedisClusterConnection<String, String> connection = redisClient.connect();
connection.sync().set("key", "value");
System.out.println(connection.sync().get("key"));
}
}go-redis Cluster (Go):
// go get github.com/redis/go-redis/v9
package main
import (
"context"
"fmt"
"io/ioutil"
"crypto/tls"
"crypto/x509"
"github.com/redis/go-redis/v9"
)
var ctx = context.Background()
func main() {
caCert, err := ioutil.ReadFile("/root/ApsaraDB-CA-Chain.pem")
if err != nil {
fmt.Println("Error loading CA certificate:", err)
return
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
RootCAs: caCertPool,
InsecureSkipVerify: true, // Not actually skipping — cert is verified in VerifyPeerCertificate
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// Validate the CA chain while skipping hostname verification.
// Reference: https://github.com/golang/go/issues/21971#issuecomment-412836078
certs := make([]*x509.Certificate, len(rawCerts))
for i, asn1Data := range rawCerts {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
panic(err)
}
certs[i] = cert
}
opts := x509.VerifyOptions{
Roots: caCertPool,
DNSName: "", // Skip hostname verification
Intermediates: x509.NewCertPool(),
}
for i, cert := range certs {
if i == 0 {
continue
}
opts.Intermediates.AddCert(cert)
}
_, err := certs[0].Verify(opts)
return err
},
}
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com:6379"},
Username: "default",
Password: "Pas***23",
TLSConfig: tlsConfig,
})
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)
}redis-cli Cluster:
# Build redis-cli with TLS support
sudo yum -y install openssl-devel gcc
wget --timeout=60 https://download.redis.io/releases/redis-7.2.0.tar.gz
tar xzf redis-7.2.0.tar.gz
cd redis-7.2.0 && make BUILD_TLS=yes
# Connect with TLS and cluster mode (-c)
./src/redis-cli -h r-2zee50zxi5iiqm****.redis.rds-aliyun.rds.aliyuncs.com -p 6379 --tls --cacert ./ApsaraDB-CA-Chain.pem -c
# Authenticate
AUTH passwordReference: Connect to Redis and Tair instances with TLS encryption
Data Structure Design
Choose the appropriate data structure based on your access patterns and business requirements. Redis provides foundational data types, while Tair extends them with enhanced structures for complex scenarios.
Redis Data Structures
| Name | Use Case |
|---|---|
| String | Caching, counters, distributed locks, session storage, rate limiting |
| Hash | Object storage (user profiles, product info), grouped field-value pairs |
| List | Message queues, latest feeds, task queues, stack/queue operations |
| Set | Unique collections, tagging, social graph (followers/friends), set operations (intersection, union) |
| Sorted Set | Leaderboards, ranking systems, priority queues, range queries by score |
| Stream | Event sourcing, log streaming, message queues with consumer groups, time-ordered events |
| Bitmap | Feature flags, online status tracking, daily active user counting, bit-level operations |
| Bitfield | Compact counters, fixed-width integer encoding, atomic increment with overflow policies |
| Geospatial | Location-based services, nearby search, geofencing, distance calculations |
| HyperLogLog | Unique visitor counting, cardinality estimation with minimal memory (0.81% error) |
Tair Data Structures
| Name | Use Case |
|---|---|
| exString (String enhancement) | Versioned strings, bounded INCRBY/INCRBYFLOAT with min/max limits, CAS/CAD for distributed locks and optimistic locking |
| exHash (Hash enhancement) | Field-level TTL expiration, field versioning, user multi-device login management, session with per-field expiry |
| exZset (Zset enhancement) | Multi-dimensional scoring (up to 256 dimensions), complex leaderboards, multi-criteria ranking |
| GIS (Geospatial enhancement) | Point/line/polygon queries, spatial relationship checks (contains, intersects), geofencing, location-based services |
| Doc (JSON) | JSON document storage with binary tree indexing, fast sub-element access, compatible with JSON standard |
| Search | Full-text search, ES-like query syntax, multi-column index, tokenization, real-time search for logs and content |
| TS (TimeSeries) | Real-time monitoring, IoT sensor data, stock tickers, two-level timeline aggregation, historical data updates |
| Bloom | Probabilistic membership testing, recommendation deduplication, crawler URL filtering, activity push management |
| Cpc | Compressed cardinality estimation, streaming analytics, rolling/sliding window aggregation, DISTINCT/COUNT/MAX/MIN |
| Roaring (Bitmap enhancement) | User segmentation, audience targeting, multi-bitmap operations, high-performance compressed bitmaps |
| Vector | Vector similarity search, LLM Chatbot, image/text multimodal retrieval, molecular structure search, HNSW indexing |
Reference:
Errors Troubleshooting
Common errors when connecting to and using Tair, with causes and solutions.
Reference: Common errors and troubleshooting
Authentication Errors
| Error | Cause | Solution |
|---|---|---|
NOAUTH Authentication required | Password not provided or incorrect | Use correct account and password. Default account: password only. Custom account: <user>:<password>. Note: If using Lettuce 6.4.0–6.4.1, this error may occur even with correct password due to CLIENT SETINFO support. Upgrade to Lettuce 6.4.2+ or Spring Data Redis 3.4.2+ |
WRONGPASS invalid username-password pair | Wrong password | Verify credentials. If using Sentinel mode, see Sentinel compatibility connection guide |
ERR invalid password | Wrong password | Check credentials. In DMS, update saved password if changed — right-click the instance, choose Edit, and enter the new password |
Connection Errors
| Error | Cause | Solution |
|---|---|---|
ERR illegal address | Client IP not in whitelist | Add client IP to instance whitelist |
ERR sentinel compatibility mode is disabled | Sentinel-compatible mode not enabled | Enable Sentinel-compatible mode in the console |
ERR max number of clients reached | Connection limit exceeded | Check for connection leaks (e.g., missing close() after JedisPool), terminate abnormal sessions, or upgrade instance |
Connection reset by peer | Client buffer exception | Check application code or adjust client buffer size |
UnknownHostException or failed to connect: xxx.redis.rds.aliyuncs.com could not be resolved | DNS resolution failure | Set correct DNS server address |
ERR must use ssl connection in ssl port | Connecting to TLS port without TLS | Enable TLS in client configuration |
NOWRITE You can't write against a non-write redis | Read-only instance during failover/upgrade | Wait for operation to complete |
Cluster Errors
| Error | Cause | Solution |
|---|---|---|
CROSSSLOT Keys in request don't hash to the same slot | Multi-key command across different slots in direct connection mode | 1) Use CLUSTER KEYSLOT to verify keys are in the same slot; 2) Use Hash Tags {tag} to group keys in same slot (avoid data skew); 3) Switch to proxy mode which supports cross-slot multi-key commands |
ERR READONLY you can't write against a read only instance | Writing to a replica node, or instance is in failover/configuration change | Connect to the primary node or wait for failover/upgrade to complete |
MOVED 3999 10.0.0.1:6379 | Key moved to another node in cluster | Use cluster-aware client (e.g., JedisCluster, RedisCluster) that handles redirection automatically |
Failed to connect to any host resolved for DNS name | DNS resolution failure for cluster nodes | Check DNS server configuration and network connectivity |
Memory and Command Errors
| Error | Cause | Solution |
|---|---|---|
OOM command not allowed when used memory > 'maxmemory' | Memory usage exceeded maxmemory limit | If total memory at 100%, upgrade instance. If only a single shard is at 100%, check for big keys using offline key analysis or instance diagnostics |
WRONGTYPE Operation against a key holding the wrong kind of value | Wrong command for data type (e.g., HASH command on String key) | Fix command to match the actual data type |
ERR unknown command 'xxx' | Command not supported by instance version | Check command support list, upgrade minor version, or switch to direct connection mode (e.g., WAIT command requires direct mode) |
ERR command 'xxx' not support for your account | Command disabled by security policy | Remove command from #no_loose_disabled-commands parameter if needed |
NOPERM this user has no permissions to run the 'xxx' | Permission denied for command | Check user permissions or remove from #no_loose_disabled-commands list |
ERR FLUSHDB is not allowed in migrating mode | FLUSHDB/FLUSHALL disabled during cluster shard scaling | Wait until shard scaling operation completes |
redis-cli Errors
| Error | Cause | Solution |
|---|---|---|
Connection reset by peer | Client buffer exception causing connection close | Check application code or adjust client buffer size |
ERR must use ssl connection in ssl port | Connecting to TLS port without TLS in redis-cli | Use --tls flag: redis-cli -h host -p port --tls -a password |
Proxy Mode Errors
| Error | Cause | Solution |
|---|---|---|
ERR client ip is not in whitelist | Client IP not in proxy whitelist (different from instance whitelist) | Add client IP to proxy whitelist in console |
NOWRITE You can't write against a non-write redis | Read-only instance during failover/upgrade | Wait for operation to complete |
ERR syntax error | Command syntax error in proxy mode | Check command syntax; some commands have different syntax in proxy mode |
ERR no such db node | Requested database node does not exist | Check if the data shard or node is available; may occur during scaling |
ERR 'xxx' command keys must in same slot | Multi-key command across slots in proxy mode | Use Hash Tags {tag} to group keys, or restructure data model |
ERR for redis cluster, eval/evalsha number of keys can't be negative or zero | EVAL/EVALSHA called without specifying key count | Ensure the NUMKEYS parameter is a positive integer when calling EVAL/EVALSHA |
ERR redis temporary failure | Sub-instance timeout, network jitter, failover, or slow query | Check slow queries, monitor failover events, verify connection limits |
ERR redis temporary failure (ErrorCode 7002) | Proxy internal error | Check instance status, retry after brief wait |
ERR request refused, too many pending request, now count xxx, beyond threshold xxx | Request queue overflow on proxy | Reduce concurrent requests, optimize slow queries, or upgrade instance |
Lua Scripts and Transaction Errors
| Error | Cause | Solution |
|---|---|---|
NOSCRIPT No matching script. Please use EVAL. | Script SHA not found in script cache | Use EVAL instead of EVALSHA, or call SCRIPT LOAD first to cache the script |
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE. | Long-running Lua script blocking the instance | Call SCRIPT KILL to terminate the script. If the script has already executed write commands, use SHUTDOWN NOSAVE (with caution) |
ERR command eval not support for normal user | EVAL/EVALSHA not available for the current account | Remove EVAL/EVALSHA from #no_loose_disabled-commands, or use an account with permission |
ERR eval/evalsha command keys must be in same slot | Keys referenced in Lua script span different slots in cluster | Use Hash Tags {tag} to ensure all keys map to the same slot |
ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array | Lua script in cluster mode does not pass keys via KEYS array | Refactor script to pass all keys via the KEYS array parameter, not hardcoded in the script body |
EXECABORT Transaction discarded because of previous errors | A command in the transaction queue failed | Check the error for the specific command that caused the failure and fix it |
UNKILLABLE Sorry the script already executed write commands against the dataset. | Cannot kill a script that has already performed writes | Wait for the script to complete, or use SHUTDOWN NOSAVE on a replica (with extreme caution) |
UNKILLABLE The busy script was sent by a master instance in the context of replication and cannot be killed. | Script from master during replication cannot be killed on replica | Wait for the master's script to complete; it will propagate through replication |
NOTBUSY No scripts in execution right now. | Called SCRIPT KILL when no script is running | No action needed — this is informational |
Jedis Client Errors
| Error | Cause | Solution |
|---|---|---|
Could not get a resource from the pool | Connection pool exhausted or instance unreachable | Check connection pool config (maxTotal, maxIdle), verify instance is accessible, check for connection leaks |
java.net.SocketTimeoutException: connect timed out | Connection establishment timeout | Check network connectivity, increase connection timeout, verify whitelist and endpoint |
java.net.SocketTimeoutException: Read timed out | Read operation timeout | Increase read timeout, check for slow queries on the instance |
No reachable node in cluster | All cluster nodes unreachable | Check cluster status, verify endpoint and port, check network connectivity |
Caused by: java.lang.NumberFormatException: For input string: "6379@13028" | Jedis version incompatible with cluster topology info format | Upgrade Jedis to latest version (3.x+) |
No more cluster attempts left | All cluster redirect attempts exhausted | Check cluster health, verify nodes are accessible, increase max attempts config |
Unexpected end of stream | Client buffer too small or connection closed by server | Increase timeout and buffer size, check for idle connection eviction |
java.lang.Long cannot be cast to java.util.List | Jedis version incompatible with server response format | Upgrade Jedis to latest version |
Broken pipe (Write failed) | Writing to a closed connection | Enable connection validation (testOnBorrow), adjust idle timeout, check for server-side connection eviction |
No way to dispatch this command to Redis Cluster because keys have different slots | Multi-key command across slots in cluster mode | Use Hash Tags {tag} to group keys, or switch to proxy mode |
Lettuce Client Errors
| Error | Cause | Solution |
|---|---|---|
Connection to xxx not allowed. This Partition is not known in the cluster view. | Cluster topology not refreshed after node change | Enable periodic cluster topology refresh: ClusterTopologyRefreshOptions.builder().enablePeriodicRefresh(true) |
io.lettuce.core.RedisConnectionException: Unable to connect xxx | Connection refused or unreachable | Check network, whitelist, endpoint, and instance status |
java.nio.channels.UnresolvedAddressException | DNS resolution failure | Set correct DNS server address, or use IP address instead of hostname |
ERR Unknown sentinel subcommand 'master' | Sentinel-compatible mode not enabled | Enable Sentinel-compatible mode in the console |
NOAUTH with correct password (Lettuce 6.4.0–6.4.1) | Lettuce CLIENT SETINFO bug | Upgrade to Lettuce 6.4.2+ or Spring Data Redis 3.4.2+. Alternatively, switch to RESP2 protocol |
RESP3 unknown command error | Some Tair instance versions do not support RESP3 protocol | Switch to RESP2 protocol in Lettuce client configuration |
Redisson Client Errors
| Error | Cause | Solution |
|---|---|---|
org.redisson.client.RedisConnectionException: Unable to connect to Redis server xxx | Connection refused or unreachable | Check network, whitelist, endpoint, and instance status |
No enum constant org.redisson.cluster.ClusterNodeInfo.Flag.NOFAILOVER | Redisson version incompatible with cluster node info format | Upgrade Redisson to latest version (3.x+) |
Spring Data Redis Client Errors
| Error | Cause | Solution |
|---|---|---|
| `NOPERM this user has no permissions to run the 'config | get' command` | Spring Data Redis tries to execute CONFIG command which is disabled |
StackExchange.Redis Client Errors
| Error | Cause | Solution |
|---|---|---|
Multiple databases are not supported on this server; cannot switch to database | Tair cluster mode only supports database 0 | Remove AllowAdmin flag, do not switch databases, ensure only database 0 is used |
Predis Client Errors
| Error | Cause | Solution |
|---|---|---|
Error while reading line from the server. | Read timeout or connection closed by server | Increase timeout, check for slow queries, verify network stability |
phpredis Client Errors
| Error | Cause | Solution |
|---|---|---|
Cannot assign requested address | Local port exhaustion (too many short-lived connections) | Enable persistent connections, increase local port range, or use connection pooling |
redis protocol error, got ' ' as reply type byte | Protocol mismatch or dirty connection | Check for RESP2/RESP3 compatibility, ensure no stale data on connection, reconnect |
php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution | DNS resolution failure | Set correct DNS server address, or use IP address instead of hostname |
Go-redis Client Errors
| Error | Cause | Solution |
|---|---|---|
panic: got 4 elements in cluster info address, expected 2 or 3 | go-redis version incompatible with Tair cluster info format | Upgrade go-redis to latest version (v9+) |
node-redis Client Errors
| Error | Cause | Solution |
|---|---|---|
| SCAN command enters infinite loop or returns empty data | Tair proxy mode may return cursor values that node-redis cannot handle properly | Use direct connection mode for SCAN operations, or handle cursor values manually in the application |
Create Instance And Connect
Use Alibaba Cloud CLI to create a Tair instance, configure network access, and verify connectivity with redis-cli.
Create Instance
Prerequisites:
Install Alibaba Cloud CLI:
# macOS
brew install aliyun-cli
# Linux (x64)
curl --connect-timeout 10 --max-time 60 -O https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
tar xzf aliyun-cli-linux-latest-amd64.tgz
sudo mv aliyun /usr/local/bin/
# Linux (arm64)
curl --connect-timeout 10 --max-time 60 -O https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-arm64.tgz
tar xzf aliyun-cli-linux-latest-arm64.tgz
sudo mv aliyun /usr/local/bin/
# Windows (PowerShell)
Invoke-WebRequest -Uri https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip -OutFile aliyun-cli.zip
Expand-Archive -Path aliyun-cli.zip -DestinationPath C:\aliyun-cliVerify installation and configure credentials (required before any API call):
aliyun version
aliyun configure # interactive: set AccessKey / Region / Language
aliyun configure set --auto-plugin-install true # required: r-kvstore commands depend on the aliyun-cli-r-kvstore pluginInstall redis-cli:
# macOS
brew install redis
# Ubuntu / Debian
sudo apt-get install redis-tools
# CentOS / RHEL
sudo yum install redis
# Windows
# Download from https://github.com/tporadowski/redis/releasesRequired parameters:
| Parameter | Description | Example |
|---|---|---|
| VPC_ID | VPC ID | vpc-bp1xxx |
| VSWITCH_ID | VSwitch ID | vsw-bp1xxx |
| PASSWORD | Instance password (8-32 chars, must include uppercase, lowercase, digits, special chars) | YourPass123! |
Optional parameters (with defaults):
| Parameter | Default |
|---|---|
| REGION_ID | cn-hangzhou |
| ZONE_ID | cn-hangzhou-h |
| INSTANCE_TYPE | tair_rdb |
| INSTANCE_CLASS | tair.rdb.1g |
| CHARGE_TYPE | PostPaid |
Example: Create Tair instance
# Set environment variables
export VPC_ID="vpc-xxx"
export VSWITCH_ID="vsw-xxx"
export PASSWORD="YourPass123!"
# Optional parameters
export REGION_ID="cn-hangzhou"
export ZONE_ID="cn-hangzhou-h"
export INSTANCE_NAME="tair-benchmark-$(date +%Y%m%d%H%M%S)"
export INSTANCE_TYPE="tair_rdb"
export INSTANCE_CLASS="tair.rdb.1g"
export CHARGE_TYPE="PostPaid"
# Create instance
aliyun r-kvstore create-tair-instance \
--biz-region-id "$REGION_ID" \
--zone-id "$ZONE_ID" \
--vpc-id "$VPC_ID" \
--vswitch-id "$VSWITCH_ID" \
--instance-name "$INSTANCE_NAME" \
--instance-type "$INSTANCE_TYPE" \
--instance-class "$INSTANCE_CLASS" \
--password "$PASSWORD" \
--charge-type "$CHARGE_TYPE" \
--shard-type "MASTER_SLAVE" \
--auto-pay true \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsSave the returned InstanceId for subsequent steps.
Example: Wait for instance ready
# Replace with your instance ID
export INSTANCE_ID="r-bp1xxxxxxxxxxxx"
# Check instance status (repeat until status is Normal or Running)
aliyun r-kvstore describe-instance-attribute \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Configure whitelist
# Option 1: Auto-detect your local public IP
MY_PUBLIC_IP=$(curl -4 -s --connect-timeout 5 --max-time 10 ifconfig.me)
# Option 2: Specify IP manually
MY_PUBLIC_IP="1.2.3.4"
# Add IP to whitelist
aliyun r-kvstore modify-security-ips \
--instance-id "$INSTANCE_ID" \
--security-ips "$MY_PUBLIC_IP" \
--security-ip-group-name "benchmark" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Allocate public connection address
# Allocate public endpoint
aliyun r-kvstore allocate-instance-public-connection \
--instance-id "$INSTANCE_ID" \
--connection-string-prefix "${INSTANCE_ID}pub" \
--port "6379" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skillsExample: Get public connection address
Public endpoint allocation is asynchronous — wait ~30s after allocate-instance-public-connection before querying or connecting.sleep 30
aliyun r-kvstore describe-db-instance-net-info \
--instance-id "$INSTANCE_ID" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-agent-skills
# Find the connection string where IPType is "Public"Common instance specifications:
| InstanceType | InstanceClass | Memory | Max Connections | Use Case |
|---|---|---|---|---|
| tair_rdb | tair.rdb.1g | 1GB | 10000 | Testing/Dev |
| tair_rdb | tair.rdb.2g | 2GB | 10000 | Small apps |
| tair_rdb | tair.rdb.4g | 4GB | 10000 | Medium apps |
| tair_rdb | tair.rdb.8g | 8GB | 10000 | Large apps |
Connect With redis-cli
After the instance is created and the public connection address is obtained, use redis-cli to connect and verify.
Example: Connect to the instance
# Authentication format for Alibaba Cloud Tair: InstanceID:Password
# Recommended: pass credentials via REDISCLI_AUTH env var (avoids leaking password in shell history / ps output)
export REDISCLI_AUTH='r-bp1xxxxxxxxxxxx:YourPass123!'
redis-cli -h r-bp1xxxxxxxxxxxxpub.redis.rds.aliyuncs.com -p 6379Example: Execute GET/SET operations
# Set a key
127.0.0.1:6379> SET hello world
OK
# Get the key
127.0.0.1:6379> GET hello
"world"
# Set with expiration (seconds)
127.0.0.1:6379> SET session:token abc123 EX 3600
OK
# Get with TTL check
127.0.0.1:6379> GET session:token
"abc123"
127.0.0.1:6379> TTL session:token
(integer) 3599
# Delete a key
127.0.0.1:6379> DEL hello
(integer) 1
# Verify deletion
127.0.0.1:6379> GET hello
(nil)Troubleshooting:
| Issue | Solution |
|---|---|
| Bad file descriptor | Clear proxy: unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy |
| Connection timeout | Check whitelist contains your public IPv4 address |
| Authentication failed | Use format InstanceID:Password, ensure password meets complexity requirements |
Performance and Monitoring
For intelligent performance monitoring and diagnostics, install and use the alibabacloud-tair-ai-assistant skill:
npx skills add aliyun/alibabacloud-aiops-skills --skill alibabacloud-tair-ai-assistant --agent <your-agent-platform>The skill provides natural language based diagnostics via Tair AI Assistant (DAS API), including:
- Instance management and configuration queries
- Performance analysis and slow query diagnostics
- Memory usage analysis and big key detection
- Hotspot key detection
- Parameter tuning guidance
- Connection troubleshooting
- Multi-turn conversation support
For full usage details, see the alibabacloud-tair-ai-assistant skill.
RAM Permissions Required — Tair DevToolset
Summary Table
| Product | RAM Action | Resource Scope | Description |
|---|---|---|---|
| R-KVStore | r-kvstore:CreateTairInstance | * | Create Tair Enterprise Edition instance |
| R-KVStore | r-kvstore:DescribeInstanceAttribute | * | Query instance attribute (status polling) |
| R-KVStore | r-kvstore:ModifySecurityIps | * | Modify IP whitelist |
| R-KVStore | r-kvstore:AllocateInstancePublicConnection | * | Allocate public connection endpoint |
| R-KVStore | r-kvstore:DescribeDBInstanceNetInfo | * | Query instance network info |
| R-KVStore | r-kvstore:ModifyBackupPolicy | * | Modify automatic backup policy |
| R-KVStore | r-kvstore:CreateBackup | * | Create a manual backup |
| R-KVStore | r-kvstore:DescribeBackups | * | Query backup sets |
| R-KVStore | r-kvstore:RestoreInstance | * | Restore instance from backup or point-in-time |
RAM Policy Document
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"r-kvstore:CreateTairInstance",
"r-kvstore:DescribeInstanceAttribute",
"r-kvstore:ModifySecurityIps",
"r-kvstore:AllocateInstancePublicConnection",
"r-kvstore:DescribeDBInstanceNetInfo",
"r-kvstore:ModifyBackupPolicy",
"r-kvstore:CreateBackup",
"r-kvstore:DescribeBackups",
"r-kvstore:RestoreInstance"
],
"Resource": "*"
}
]
}Notes
- The above permissions are the minimum permission set required by this Skill
- For read-only queries (without creating/deleting resources), only
Describe*permissions are needed - It is recommended to limit
Resourceto specific instance ARN in production environments
Related CLI Commands — Tair Skill
R-KVStore Product Commands
| CLI Command | API | Description |
|---|---|---|
aliyun r-kvstore create-tair-instance | CreateTairInstance | Create Tair Enterprise Edition cloud-native instance |
aliyun r-kvstore describe-instance-attribute | DescribeInstanceAttribute | Query instance attribute (including status) |
aliyun r-kvstore modify-security-ips | ModifySecurityIps | Configure IP whitelist |
aliyun r-kvstore allocate-instance-public-connection | AllocateInstancePublicConnection | Allocate public connection endpoint |
aliyun r-kvstore describe-db-instance-net-info | DescribeDBInstanceNetInfo | Query instance network info |
Key Parameters Reference
create-tair-instance
| Parameter | Required | Description |
|---|---|---|
--biz-region-id | Yes | Region ID, e.g. cn-hangzhou |
--instance-class | Yes | Instance specification, e.g. tair.rdb.1g |
--instance-type | Yes | Instance series: tair_rdb / tair_scm / tair_essd |
--vpc-id | Yes | VPC ID |
--vswitch-id | Yes | VSwitch ID |
--password | No | Connection password (8-32 chars, at least 3 of: uppercase, lowercase, digits, special chars) |
--charge-type | No | Billing method: PostPaid (pay-as-you-go) / PrePaid (subscription) |
--auto-pay | No | Whether to auto pay |
--shard-type | No | Shard type: MASTER_SLAVE (default) / STAND_ALONE |
--zone-id | No | Zone ID |
--instance-name | No | Instance name |
describe-instance-attribute
| Parameter | Required | Description |
|---|---|---|
--instance-id | Yes | Instance ID |
modify-security-ips
| Parameter | Required | Description |
|---|---|---|
--instance-id | Yes | Instance ID |
--security-ips | Yes | Whitelist IPs, separated by commas |
--security-ip-group-name | No | Whitelist group name |
--modify-mode | No | Modify mode: Cover / Append / Delete |
allocate-instance-public-connection
| Parameter | Required | Description |
|---|---|---|
--instance-id | Yes | Instance ID |
--connection-string-prefix | Yes | Public connection prefix (lowercase, 8-40 chars) |
--port | Yes | Port number (1024-65535) |
describe-db-instance-net-info
| Parameter | Required | Description |
|---|---|---|
--instance-id | Yes | Instance ID |
Success Verification Method — Tair DevToolset
Scenario Goal
Expected Outcome: Tair Enterprise Edition instance created successfully, public TCP port reachable.
---
Step-by-Step Verification
1. Verify Instance Creation Success
aliyun r-kvstore describe-instance-attribute \
--instance-id "${INSTANCE_ID}" \
--cli-query "Instances.DBInstanceAttribute[0].InstanceStatus" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetSuccess Indicator: Return value is Normal
2. Verify Whitelist Configuration
aliyun r-kvstore describe-security-ips \
--instance-id "${INSTANCE_ID}" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetSuccess Indicator: Returned SecurityIpGroups contains benchmark group, and IP address matches local public IP.
3. Verify Public Endpoint Allocation
aliyun r-kvstore describe-db-instance-net-info \
--instance-id "${INSTANCE_ID}" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-tair-devtoolsetSuccess Indicator: Returned NetInfoItems.InstanceNetInfo contains a record with IPType as Public, and ConnectionString is not empty.