3

I would like to get all the keys from Redis cluster using Jedis with the following code snippet:

 public void testRedis() {
        String key = "*";
        ScanParams scanParams = new ScanParams().count(1000).match("{*}");
        String cur = SCAN_POINTER_START;
        do {
            ScanResult<String> scanResult = getRedisCluster().scan(cur, scanParams);
            scanResult.getResult().stream().forEach(System.out::println);
            cur = scanResult.getStringCursor();
        } while (!cur.equals(SCAN_POINTER_START));
    }

My problem is that it doesn't return any result with this solution. Even if I specify the matching pattern for an existing key it's still not working. I tried to get specific keys with get command it returns value without any error, so the connection seems good.

Any suggestion? (One of my clue is that match parameter waiting for "curly-brackets" so I had to add there, but I haven't seen using this like that on internet anywhere.)

sazzad
  • 5,740
  • 6
  • 25
  • 42
Twi
  • 765
  • 3
  • 13
  • 29

2 Answers2

8

You can get all keys of a cluster by getting keys from each node and unifying them.

getClusterNodes() method will come in handy which returns a map of all cluster nodes.

Here is an implementation using SCAN, similar to your attempt:

public void testRedis() {
    ScanParams scanParams = new ScanParams().count(1000);
    Set<String> allKeys = new HashSet<>();
    getRedisCluster().getClusterNodes().values().forEach((pool) -> {
        String cur = ScanParams.SCAN_POINTER_START;
        do {
            try (Jedis jedis = pool.getResource()) {
                ScanResult<String> scanResult = jedis.scan(cur, scanParams);
                allKeys.addAll(scanResult.getResult());
                cur = scanResult.getStringCursor();
            }
        } while (!cur.equals(ScanParams.SCAN_POINTER_START));
    });
    allKeys.stream().forEach(System.out::println);
}

Update: You can check conditions to stop iteration right after getting at least 1000 keys.

public void testRedis() {
    ScanParams scanParams = new ScanParams().count(1000);
    Set<String> allKeys = new HashSet<>();
    for (JedisPool pool : getRedisCluster().getClusterNodes().values()) {
        String cur = ScanParams.SCAN_POINTER_START;
        do {
            try (Jedis jedis = pool.getResource()) {
                ScanResult<String> scanResult = jedis.scan(cur, scanParams);
                allKeys.addAll(scanResult.getResult());
                cur = scanResult.getStringCursor();
            }
            if (allKeys.size() >= 1000) break;
        } while (!cur.equals(ScanParams.SCAN_POINTER_START));
        if (allKeys.size() >= 1000) break;
    }
    allKeys.stream().forEach(System.out::println);
}
sazzad
  • 5,740
  • 6
  • 25
  • 42
  • The scan solution looks really nice, but It doesn't stop even if it has 1000 keys in the set, because the iterator has not finished. What is a good solution to stop and not get all the keys? – Twi May 07 '18 at 14:47
1

The pattern from the match method should be "*" instead of "{*}"

Liviu Stirb
  • 5,876
  • 3
  • 35
  • 40
  • If I do this I get this error message always: java.lang.IllegalArgumentException: JedisCluster only supports SCAN commands with MATCH patterns containing hash-tags ( curly-brackets enclosed strings )) – Twi Apr 25 '18 at 13:08
  • That's why it throws the execption: http://atetric.com/atetric/javadoc/redis.clients/jedis/2.9.0/src-html/redis/clients/util/JedisClusterHashTagUtil.html#line.17 – Twi Apr 25 '18 at 13:13
  • @Twi just ran this with one redis instead of a cluster and it works. I used jedis 2.9.0 – Liviu Stirb Apr 26 '18 at 08:14
  • Yes, but I need with cluster. It works with one redis I know, but I need the same with Cluster – Twi Apr 26 '18 at 11:33