Redis/Jedis - Delete by pattern?
Asked Answered
C

5

15

Normally, I get the key set then use a look to delete each key/value pair.

Is it possible to just delete all keys via pattern?

ie:

Del sample_pattern:*
Cotsen answered 23/1, 2014 at 19:23 Comment(0)
C
24

It seems, for Jedis, to "delete by pattern" is basically getting all the keys of a specific pattern then loop through it.

ie

Set<String> keys = jedis.keys(pattern);
for (String key : keys) {
    jedis.del(key);
} 
Cotsen answered 27/1, 2014 at 17:10 Comment(2)
Scan is better. But you can reduce the number of call to jedis by doing Set<String> keys = jedis.keys(pattern); jedis.del(keys.toArray(new String[keys.size()]));Markle
A more efficient way to do it without using KEYS can be found below: https://mcmap.net/q/756428/-redis-jedis-delete-by-patternCorrey
L
22

KEYS is not recommended to use due to its inefficiencies when used in production. Please see https://redis.io/commands/keys. Instead, it is better to use SCAN. Additionally, a more efficient call than repeated calls to jedis.del() is to make one single call to jedis to remove the matching keys, passing in an array of keys to delete. A more efficient solution is presented below:

Set<String> matchingKeys = new HashSet<>();
ScanParams params = new ScanParams();
params.match("sample_pattern:*");

try(Jedis jedis = jedisPoolFactory.getPool().getResource()) {
    String nextCursor = "0";

    do {
        ScanResult<String> scanResult = jedis.scan(nextCursor, params);
        List<String> keys = scanResult.getResult();
        nextCursor = scanResult.getStringCursor();

        matchingKeys.addAll(keys);

    } while(!nextCursor.equals("0"));

    if (matchingKeys.size() == 0) {
      return;
    }

    jedis.del(matchingKeys.toArray(new String[matchingKeys.size()]));
}
Laywoman answered 9/3, 2017 at 18:18 Comment(4)
I wonder twho things - why KEYS is so ineffective, and whether SCANning of non-trivial entries (say, 10kb JSONs) is really more effective than using KEYS. I mean - keys is basically like SCAN, only dropping the content and returning in one bulk. Which wou need to do here anyway.Mcgrath
Since Redis is generally considered to be single-threaded, the KEYS command could block for seconds if the set is sufficiently large. In many production environments, waiting for even a couple milliseconds could cause major performance problems since Redis is assumed to be fast.Coniine
Much more efficient than the answer marked as correct. Thank you. However, you must instantiate jedisPool before using it in the try block: JedisPool jedisPool = new JedisPool(); Further, all that needs to be called is jedisPool.getResource(). The factory part is no longer necessary, nor is the .getPool() method called on it.Correy
I think scanResult.getStringCursor() is deprecated. Replaced with scanResult.getCursor().Groos
P
7

You should try using eval. I'm no Lua expert, but this code works.

private static final String DELETE_SCRIPT_IN_LUA =
    "local keys = redis.call('keys', '%s')" +
    "  for i,k in ipairs(keys) do" +
    "    local res = redis.call('del', k)" +
    "  end";

public void deleteKeys(String pattern) {
  Jedis jedis = null;

  try {
    jedis = jedisPool.getResource();

    if (jedis == null) {
      throw new Exception("Unable to get jedis resource!");
    }

    jedis.eval(String.format(DELETE_SCRIPT_IN_LUA, pattern));  
  } catch (Exception exc) {
    if (exc instance of JedisConnectionException && jedis != null) {
      jedisPool.returnBrokenResource(jedis);
      jedis = null;
    }

    throw new RuntimeException("Unable to delete that pattern!");
  } finally {
    if (jedis != null) {
      jedisPool.returnResource(jedis);
    }
  }
}

And then call:

deleteKeys("temp:keys:*");

This guarantees a one server-side call, multiple delete operation.

Pilose answered 3/5, 2014 at 12:1 Comment(0)
J
6

You can do it with the Redisson in one line:

redisson.getKeys().deleteByPattern(pattern)
Johanna answered 29/11, 2015 at 16:49 Comment(1)
this would be useful for me thanksStrangury
L
0

You can do it with bash:

$ redis-cli KEYS "sample_pattern:*" | xargs redis-cli DEL
Librium answered 23/1, 2014 at 19:26 Comment(5)
sorry, forgot to mention that i want to do this in java code. but this is useful.Cotsen
@yaojiang I never wrote a line of Java but here's my take, see the updated answer.Librium
no dice. it looks like the jedis implementation only allows me to do something like jedis.del(key1, key2, key3,...);Cotsen
@yaojiang Oh, I thought jedis.keys() would return a collection of keys. What does it return btw?Librium
one or more string args, or byte[].Cotsen

© 2022 - 2024 — McMap. All rights reserved.