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 包装器方面让我感到困惑。有ScanResults
和ScanParameter
类在流动,我对如何正确使用它们没有明确的概念。此功能的文档不存在或至少很难找到。谁能指出在哪里可以找到关于如何使用 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.Iterator
或java.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命令的主要内容,如果未能解决你的问题,请参考以下文章