Lettuce Scan解决/Scan is not suppo

2021-07-13  本文已影响0人  李不言被占用了

问题

spring-data-redis中没有实现关于redis集群的很多命令,最近碰到lettuce在集群中无法执行scan命令的情况。异常如下:

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Scan is not supported across multiple nodes within a cluster.

解决

查看官方文档,发现其实lettuce其实是能支持这种跨节点命令的。官方文档-redis-cluster.cross-slot-command-routing

其中提到了几个类可以执行跨节点命令:

RedisAdvancedClusterCommands
RedisAdvancedClusterAsyncCommands
RedisAdvancedClusterReactiveCommands

根据官方例子

写出大概如下代码即可:


// 获取RedisAdvancedClusterCommands
LettuceClusterConnection con = (LettuceClusterConnection)redisTemplate.getConnectionFactory().getClusterConnection();// 能从LettuceConnetionFactory中直接获取到AbstractRedisClient更好
RedisAdvancedClusterAsyncCommands<byte[], byte[]> nativeConnection = (RedisAdvancedClusterAsyncCommands)con.getNativeConnection();
RedisAdvancedClusterCommands<byte[], byte[]> sync = nativeConnection.getStatefulConnection().sync();

// Cursor及pattern设置
KeyScanCursor<byte[]> scanCursor = null;
ScanArgs scanArgs = new ScanArgs();
scanArgs.match("user:*");

do {

    if (scanCursor == null) {
        scanCursor = sync.scan(scanArgs);
    } else {
        scanCursor = sync.scan(scanCursor, scanArgs);
    }
    keyList.addAll(scanCursor.getKeys());
} while (!scanCursor.isFinished());

// 输出
keyList.forEach(bytes -> {
    String s = new String(bytes);
    System.out.println(s);
});

ScanArgs配置一下limit属性,性能会更好

源码

Lettuce中集群scan的实现参照源码:io.lettuce.core.cluster.RedisAdvancedClusterAsyncCommandsImpl#scan(io.lettuce.core.output.KeyStreamingChannel<K>, io.lettuce.core.ScanCursor)

大致思路是:逐个节点执行。

后记

可能有更好的方法,以后发现了再补充。

上一篇下一篇

猜你喜欢

热点阅读