产品动态
公告
-ERR invalid cursor(master node idx out of range)\\r\\n),此异常说明游标绑定的历史分片状态已失效。若强行忽略错误继续迭代,不仅无法获取有效数据,更会因游标与分片逻辑不同步进入死循环,严重消耗系统资源。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.*;/*** Redis服务实现类*/public class RedisServiceImpl implements RedisService {//scan最大重试次数private static final int MAX_RETRIES = 3;private final RedisConnectionFactory connectionFactory;/*** 构造函数*/public RedisServiceImpl() {this.connectionFactory = RedisConnectionFactory.getInstance();}/*** scan最佳实践* @param pattern 匹配的模式* @param count 每次迭代返回的 key 的数量*/@Overridepublic 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();// 对scan过程的报错进行捕获,遇到报错从0开始重新scan扫描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();// 处理获取到的键 - 业务逻辑processKeysWithBusinessLogic(keys);}cursor = scanResult.getCursor();// 游标为"0"时完成扫描if (cursor.equals(ScanParams.SCAN_POINTER_START)) {long endTime = System.currentTimeMillis();double timeElapsed = (endTime - startTime) / 1000.0;System.out.println("\\n🎉 扫描完成!");System.out.println("总批次数: " + totalBatches);System.out.println("总键数: " + totalKeysProcessed);System.out.println("扫描耗时: " + timeElapsed + " 秒");System.out.println("平均速度: " + (totalKeysProcessed / timeElapsed) + " 键/秒");scanCompleted = true;break;}}} catch (Exception e) {retryCount++;System.err.println("⚠️ 扫描过程中发生错误,尝试从0开始重新扫描 (" + retryCount + "/" + MAX_RETRIES + ")");e.printStackTrace();// 超过最大重试次数,终止重试if (retryCount > MAX_RETRIES) {throw new RuntimeException("达到最大重试次数 (" + MAX_RETRIES + "),扫描失败", e);}}}} catch (Exception e) {System.err.println("扫描键失败: " + e.getMessage());e.printStackTrace();}}/*** 处理键的业务逻辑*/private void processKeysWithBusinessLogic(List<String> keys) {// 业务处理逻辑....System.out.println(keys.size());}}
文档反馈