tencent cloud

Tencent Cloud Distributed Cache (Redis OSS-Compatible)

Berita Terkini dan Pengumuman
Catatan Rilis
Pengumuman
Pengenalan Produk
Ikhtisar
Keunggulan
Kasus Penggunaan
Mesin Penyimpanan
Product Series
Performa
Pemisahan Baca/Tulis
Deployment Multi-AZ
Wilayah dan AZ
Panduan Pembelian
Ikhtisar Penagihan
Metode Pembelian
Pembayaran Jatuh Tempo
Memulai
Membuat Instans TencentDB for Redis
Menghubungkan ke Instans TencentDB for Redis (melalui Jaringan Pribadi)
Panduan Pengoperasian
Ikhtisar Operasi
Koneksi SDK
Manajemen dan Pemeliharaan Instans
Peningkatan Instans
Manajemen Deployment Multi-AZ
Pencadangan dan Pemulihan
Manajemen akun
Konfigurasi Parameter
Manajemen Akses
Jaringan dan Keamanan
Pemantauan dan Peringatan Alarm
Replikasi Global
Service Agreement
Service Level Agreement
Terms of Service
Glosarium
ドキュメントTencent Cloud Distributed Cache (Redis OSS-Compatible)

Global SCAN Guide for Cluster Architecture

フォーカスモード
フォントサイズ
最終更新日: 2026-04-01 10:47:41

Basic Introduction

Tencent Cloud Distributed Cache 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 Tencent Cloud Distributed Cache 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());
}
}

ヘルプとサポート

この記事はお役に立ちましたか?

フィードバック