美文网首页
Lettuce Scan解决/Scan is not suppo

Lettuce Scan解决/Scan is not suppo

作者: 李不言被占用了 | 来源:发表于2021-07-13 10:07 被阅读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)

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

    后记

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

    相关文章

      网友评论

          本文标题:Lettuce Scan解决/Scan is not suppo

          本文链接:https://www.haomeiwen.com/subject/hrvjpltx.html