众所周知,当redis中key数量越大,keys 命令执行越慢,而且最重要的会阻塞服务器,对单线程的redis来说,简直是灾难,而scan用来遍历数据则是一个不错的选择。
话不多说直接上代码 源码下载
相关操作类 迭代处理器ScanProcessor 和 返回值KeysScanResult
package test.util.redis;
import java.util.List;
/**
* Author: zhaoyj
* Date: 2019/3/28 11:04
* Description: redis key迭代处理器
*/
public interface ScanProcessor {
public void batchProcessing(List<String> keyList) throws Exception;
}
package test.util.redis;
/**
* Author: zhaoyj
* Date: 2019/3/29 16:19
* Description:
*/
public class KeysScanResult {
private Integer scanSize;
private Integer iterations;
private Long dataCount;
public Integer getScanSize() {
return scanSize;
}
public void setScanSize(Integer scanSize) {
this.scanSize = scanSize;
}
public Integer getIterations() {
return iterations;
}
public void setIterations(Integer iterations) {
this.iterations = iterations;
}
public Long getDataCount() {
return dataCount;
}
public void setDataCount(Long dataCount) {
this.dataCount = dataCount;
}
}
keys方法复写
ScanProcessor 是一个回调类,每迭代查询scanSize个就回调一次。
public KeysScanResult keys(String pattern, int scanSize, ScanProcessor scanProcessor) throws Exception {
KeysScanResult keysScanResult = new KeysScanResult();
keysScanResult.setScanSize(scanSize);
keysScanResult.setIterations(0);
keysScanResult.setDataCount(0L);
Jedis jedis = null;
try {
jedis = getJedis();
ScanParams scanParams = new ScanParams();
scanParams.match(pattern);
scanParams.count(scanSize);
String scanRet = "0";
do {
ScanResult<String> scan = jedis.scan(scanRet, scanParams);
List<String> result = scan.getResult();
//游标处理
scanRet = scan.getStringCursor();
//数据处理
scanProcessor.batchProcessing(result);
//数据统计
keysScanResult.setIterations(keysScanResult.getIterations() + 1);
keysScanResult.setDataCount(keysScanResult.getDataCount() + result.size());
} while (!scanRet.equals("0"));
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw e;
} finally {
returnResource(jedis);
}
return keysScanResult;
}
protected Jedis getJedis() throws Exception {
Jedis jedis = jedisPool.getResource();
if (DEFAULT_DATABASE == null) {
throw new Exception("DEFAULT_DATABASE IS NULL");
}
jedis.select(DEFAULT_DATABASE);
return jedis;
}
private Integer DEFAULT_DATABASE = 0;
private JedisPool jedisPool;
具体使用
redisManager.keys("*", 100, new ScanProcessor() {
@Override
public void batchProcessing(List<String> keyList) throws Exception {
System.out.println(Arrays.toString(keyList.toArray()));
}
});