一.scan前言
- 从Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键。
对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险,从而也让一些操作可以放在主节点上执行。
二. 需求说明
- 公司项目是内网系统,没有并发量,由于第三方接口响应太慢,该接口的数据需频繁使用。项目经理强烈不满,认为应该效率换内存空间,要求数据时效性T+1,于是就有了将接口数据的所需字段存入redis中,每日增量更新。
三.使用scan命令实现redis模糊匹配分页查询
private List<String> findKeysForPage(String patternKey, int pageNum, int pageSize) {
ScanOptions options = ScanOptions.scanOptions().match(patternKey).count(10000).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = factory.getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<String>(pageSize);
int tmpIndex = 0;
int startIndex = (pageNum - 1) * pageSize;
int end = pageNum * pageSize;
while (cursor.hasNext()) {
if (tmpIndex >= startIndex && tmpIndex < end) {
byte[] key = cursor.next();
if (key == null || key.length == 0) {
break;
}
String keyStr = new String(key);
result.add(keyStr);
tmpIndex++;
continue;
}
if (tmpIndex >= end) {
break;
}
tmpIndex++;
cursor.next();
}
try {
cursor.close();
} catch (Exception e) {
e.printStackTrace();
log.error("cursor.close(); redis连接关闭异常 {}", e.getMessage());
}
try {
RedisConnectionUtils.releaseConnection(rc, factory);
} catch (Exception e) {
e.printStackTrace();
log.error(" RedisConnectionUtils.releaseConnection(rc, factory); redis连接关闭异常 {}", e.getMessage());
}
return result;
}
public List getListByKeys(List keyList) {
return redisTemplate.opsForValue().multiGet(keys);
}