tencent cloud

Tencent Cloud Distributed Cache (Redis OSS-Compatible)

Release Notes and Announcements
Release Notes
Announcements
User Tutorial
Product Introduction
Overview
Product Strengths
Use Cases
Storage Engine
Product Series
Product Versions
Specifications and Performance
Read/Write Separation
Multi-AZ Deployment
Regions and AZs
Terms
Service Regions and Service Providers
Purchase Guide
Billing Overview
Pricing Center
Instance Purchasing
Renewal (Yearly/Monthly Subscription)
Refund (Yearly/Monthly Subscription)
Overdue Payments
Switching from Pay-as-You-Go to Yearly/Monthly Subscription
Getting Started
Quickly Creating an Instance
Connecting to Redis Instance
Operation Guide
Operation Overview
Connecting to a Database Instance
Managing Instances
Upgrade Instance
Management Node (Redis/ValKey Edition)
Multi-AZ Deployment Management
Backup and Restoration
Managing Accounts
Parameter Configuration
Slow Query
Access Management
Network and Security
Monitoring and Alarms
Event Management (Redis/ValKey Edition)
Data Migration
Global Replication for Redis Edition
Performance Optimization
Sentinel Mode
Development Guidelines
Naming Rules
Basic Usage Guidelines
Design Principles of Key and Value
Command Usage Guidelines
Design Principles of Client Programs
Connection Pool Configuration
Command Reference
Command Reference Overview
Redis Edition and Valkey Edition Command Compatibility
Version Command Usage Differences
Differences Between the Proxy Architecture and Direct Connection Mode
More Command Operations (Redis/Valkey Edition)
Memcached Edition Command Compatibility
Practical Tutorial
Building TencentDB for Redis® Client Monitoring Based on Spring Boot
Redis Client Connection Configuration Policy and Practice
Global SCAN Guide for Cluster Architecture
Eliminating Instances Securely
Hot Key and Big Key
AZ Migration Scheme
Troubleshooting
Connection Exception
Exception Analysis and Solution of Redisson Client Timeout Reconnection
Performance Troubleshooting and Fine-Tuning
API Documentation
History
Introduction
API Category
Making API Requests
Instance APIs
Parameter Management APIs
Other APIs
Backup and Restoration APIs
Region APIs
Monitoring and Management APIs
Log APIs
Data Types
Error Codes
FAQs
General
Connection and Login
Purchase
Service Agreement
Service Level Agreement
Terms of Service
Glossary
Contact Us

Global SCAN Guide for Cluster Architecture

PDF
Focus Mode
Font Size
Last updated: 2026-03-17 18:23:48

Basic Introduction

Tencent Cloud TencentDB for Redis® Cluster Edition addresses the limitation that native Redis Cluster does not support global SCAN through an innovative Proxy architecture. In native Redis Cluster, data is distributed across multiple shard nodes, making cross-node scan operations impossible. Tencent Cloud supports two precise scan modes through the extended SCAN command feature: users can achieve targeted scan for specific shard nodes by appending the NODEID parameter to the end of the command. Additionally, starting from Proxy 5.8.9, global SCAN operations without node restrictions are fully supported, enabling complete traversal of all shard data.

Use Limits

When a node switch (change of primary and secondary roles) or shard reduction (cluster scale-in) occurs in the cluster, it may trigger rare invalidation of the SCAN cursor, causing a disconnection of the mapping relationship between the shard index corresponding to the cursor and the actual node. If the original cursor is still used to perform scans, the system will throw an error, for example, -ERR invalid cursor(master node idx out of range)\\r\\n. It indicates that the status of the historical shard bound to the cursor has become invalid. If the error is forcibly ignored and the iteration continues, the valid data cannot be obtained, and a dead loop may occur due to the asynchronization between the cursor and shard logic, severely consuming system resources.

Reference Code

In a TencentDB for Redis® cluster environment, when SCAN operations are performed, if a cursor exception is captured due to changes in the cluster topology, it is required to reset the cursor to the initial position of 0 and restart the global scan process. This policy directly mitigates the risk of cursor dead loops caused by invalid shard indexes, ensuring the integrity and security of data traversal. The following code implements a secure key scan feature based on the Redis SCAN command, specifically addressing the key traversal needs of large Redis databases. For specific connection configuration, see Jedis Connecting to Redis.
package com.example.service.impl;
import com.example.config.RedisConnectionFactory;
import com.example.service.RedisService;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.ScanParams;
import redis.clients.jedis.resps.ScanResult;
import java.util.*;
/**
* TencentDB for Redis® service implementation class.
*/
public class RedisServiceImpl implements RedisService {
//scan Maximum number of retries.
private static final int MAX_RETRIES = 3;
private final RedisConnectionFactory connectionFactory;
/**
* Construction function.
*/
public RedisServiceImpl() {
this.connectionFactory = RedisConnectionFactory.getInstance();
}
/**
* scan Best practices.
* @param pattern Matching mode.
* @param count Number of returned keys for each iteration.
*/
@Override
public void scanKeys(String pattern, int count) {
try (Jedis jedis = connectionFactory.getConnection()) {
int retryCount = 0;
boolean scanCompleted = false;
int totalKeysProcessed = 0;
int totalBatches = 0;
long startTime = System.currentTimeMillis();
// Capture the reported errors during the scan process and restart the scan from 0 upon encountering an error.
while (!scanCompleted && retryCount <= MAX_RETRIES) {
String cursor = ScanParams.SCAN_POINTER_START;
ScanParams scanParams = new ScanParams();
scanParams.count(count);
scanParams.match(pattern);
try {
while (true) {
ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
List<String> keys = scanResult.getResult();
totalBatches++;
if (!keys.isEmpty()) {
totalKeysProcessed += keys.size();
// Process the obtained keys - business logic.
processKeysWithBusinessLogic(keys);
}
cursor = scanResult.getCursor();
// Scan is completed when the cursor is "0".
if (cursor.equals(ScanParams.SCAN_POINTER_START)) {
long endTime = System.currentTimeMillis();
double timeElapsed = (endTime - startTime) / 1000.0;
System.out.println("\\n🎉 Scan completed.");
System.out.println("Total number of batches: " + totalBatches);
System.out.println("Total number of keys: " + totalKeysProcessed);
System.out.println("Scan duration: " + timeElapsed + " Second");
System.out.println("Average speed: " + (totalKeysProcessed / timeElapsed) + " Key/Second");
scanCompleted = true;
break;
}
}
} catch (Exception e) {
retryCount++;
System.err.println("⚠️ An error occurs during scanning, and attempting to rescan from 0. (" + retryCount + "/" + MAX_RETRIES + ")");
e.printStackTrace();
// The maximum number of retries is exceeded, and the retry is terminated.
if (retryCount > MAX_RETRIES) {
throw new RuntimeException("Maximum number of retries is reached. (" + MAX_RETRIES + "),Scan failed.", e);
}
}
}
} catch (Exception e) {
System.err.println("Scanning keys failed.: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Business logic of processing keys.
*/
private void processKeysWithBusinessLogic(List<String> keys) {
// Business processing logic....
System.out.println(keys.size());
}
}

Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback