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:*
SANN3
  • 9,459
  • 6
  • 61
  • 97
iCodeLikeImDrunk
  • 17,085
  • 35
  • 108
  • 169

5 Answers5

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);
} 
iCodeLikeImDrunk
  • 17,085
  • 35
  • 108
  • 169
  • 4
    Scan is better. But you can reduce the number of call to jedis by doing `Set keys = jedis.keys(pattern); jedis.del(keys.toArray(new String[keys.size()]));` – dbaq Apr 17 '17 at 21:59
  • A more efficient way to do it without using KEYS can be found below: https://stackoverflow.com/a/42702672/11150418 – AlgoTrading Mar 23 '22 at 21:50
21

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()]));
}
petertc
  • 3,607
  • 1
  • 31
  • 36
Aprille
  • 311
  • 2
  • 5
  • 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. – Ondra Žižka Jan 30 '18 at 14:58
  • 3
    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. – Kirk Backus Jun 05 '18 at 19:50
  • 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. – AlgoTrading Mar 23 '22 at 21:31
  • I think `scanResult.getStringCursor()` is deprecated. Replaced with `scanResult.getCursor()`. – NanoNova Jun 13 '22 at 06:19
6

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.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
corindiano
  • 724
  • 7
  • 6
5

You can do it with the Redisson in one line:

redisson.getKeys().deleteByPattern(pattern)
Nikita Koksharov
  • 10,283
  • 1
  • 62
  • 71
0

You can do it with bash:

$ redis-cli KEYS "sample_pattern:*" | xargs redis-cli DEL
Agis
  • 32,639
  • 3
  • 73
  • 81