Jedis中如何使用SCAN命令

Posted

技术标签:

【中文标题】Jedis中如何使用SCAN命令【英文标题】:How to use SCAN commands in Jedis 【发布时间】:2016-02-23 20:19:00 【问题描述】:

我使用 redis 和 jedis 已经有一段时间了,到目前为止从未需要 SCAN 命令。但是现在我需要使用SCAN 命令,尤其是hscan。我了解它在 redis 级别上的工作原理,但是 jedis Java 包装器方面让我感到困惑。有ScanResultsScanParameter 类在流动,我对如何正确使用它们没有明确的概念。此功能的文档不存在或至少很难找到。谁能指出在哪里可以找到关于如何使用 hscan 和 jedis 迭代哈希的好例子?

很抱歉没有代码,但到目前为止我尝试的方法毫无意义。

【问题讨论】:

尝试查看 Jedis 的资源,特别是测试 - 他们通常会提供线索:github.com/xetorthio/jedis/blob/master/src/test/java/redis/… 感谢您的指点。但是,测试似乎并没有真正迭代哈希。例如,我只能看到一个对 hscan 的调用。我仍然缺少当前光标作为字符串的概念。 【参考方案1】:

在回答自己问题的良好传统中,我发现了以下内容:

String key = "THEKEY";
ScanParams scanParams = new ScanParams().count(100);
String cur = redis.clients.jedis.ScanParams.SCAN_POINTER_START; 
boolean cycleIsFinished = false;
while(!cycleIsFinished) 
  ScanResult<Entry<String, String>> scanResult = 
        jedis.hscan(key, cur, scanParams);
  List<Entry<String, String>> result = scanResult.getResult();

  //do whatever with the key-value pairs in result

  cur = scanResult.getStringCursor();
  if (cur.equals("0")) 
    cycleIsFinished = true;
                   

重要的是 cur 是一个字符串变量,如果扫描完成,它是"0"

在 ScanParams 的帮助下,我能够定义每个块的大致大小以从哈希中获取。近似,因为在扫描过程中散列可能会发生变化,所以可能是一个元素在循环中被返回了两次。

【讨论】:

【参考方案2】:

我不喜欢标志变量

Jedis jedis = new Jedis("localhost");

ScanParams scanParams = new ScanParams().count(10).match("*");
String cur = SCAN_POINTER_START;
do 
    ScanResult<String> scanResult = jedis.scan(cur, scanParams);

    // work with result
    scanResult.getResult().stream().forEach(System.out::println);
    cur = scanResult.getStringCursor();
 while (!cur.equals(SCAN_POINTER_START));

【讨论】:

【参考方案3】:

对上述示例的建议。您可以在 scanParams 类中指定键匹配。见下文。

ScanParams scanParams = new ScanParams();
    scanParams.match("*");

    String cursor = redis.clients.jedis.ScanParams.SCAN_POINTER_START;
    boolean cycleIsFinished = false;
    while (!cycleIsFinished) 

        ScanResult<String> scanResult = jedisRead.scan(cursor, scanParams);
        List<String> result = scanResult.getResult();

        /*
         * do what you need to do with the result
         */



        cursor = scanResult.getStringCursor();
        if (cursor.equals("0")) 
            cycleIsFinished = true;
        
    

【讨论】:

【参考方案4】:

如果你习惯使用java.util.Iteratorjava.lang.Iterable接口,那么你可以试试基于Redis的框架Redisson。

这是一个示例,如何迭代存储在 Redis 中的名为“myMap”的地图的所有

RedissonClient redissonClient = RedissonClient.create(config);

// implements java.util.concurrent.ConcurrentMap interface
RMap<String, String> map = redissonClient.getMap("myMap");

// default batch size on each HSCAN invocation is 10
for (String key: map.keySet()) 
    ...


// default batch size on each HSCAN invocation is 250
for (String key: map.keySet(250)) 
    ...

这是一个如何迭代存储在 Redis 中的所有 keys 的示例:

RedissonClient redissonClient = RedissonClient.create(config);

RKeys keys = redissonClient.getKeys();

// default batch size on each SCAN invocation is 10
for (String key: keys.getKeys()) 
    ...


// default batch size on each SCAN invocation is 250
for (String key: keys.getKeys(250)) 
    ...

是不是很简单?

【讨论】:

他问的是 Jedis,而不是 Redisson。【参考方案5】:

(派对迟到了,我知道) 我是位于 github 上的名为 InterruptingJedisLocks 的库的开发人员。

我的类 ScanIterable/ScanIterator 是在底层使用 SCAN 操作的迭代器;使其更容易在 Java 中操作,隐藏复杂性。 ScanUtils 类也是一个很好的帮手。

随意将它与库或仅 Java 类一起使用

【讨论】:

以上是关于Jedis中如何使用SCAN命令的主要内容,如果未能解决你的问题,请参考以下文章

jedis中scan的实现

如何停止hbase的scan命令

Jedis scan及其count的值

IDEA使用Jedis访问操作Redis数据库

rediskey如何使用支持中文

如何批量删除redis中keys