Redis/Jedis – удалить по шаблону?

Обычно я получаю набор ключей, а затем использую поиск для удаления каждой пары ключ/значение.

Можно ли просто удалить все ключи с помощью шаблона?

ie:

Del sample_pattern:*

person iCodeLikeImDrunk    schedule 23.01.2014    source источник


Ответы (5)


Кажется, что для джедаев «удалить по шаблону» в основном нужно получить все ключи определенного шаблона, а затем пройтись по нему.

ie

Set<String> keys = jedis.keys(pattern);
for (String key : keys) {
    jedis.del(key);
} 
person iCodeLikeImDrunk    schedule 27.01.2014
comment
Скан лучше. Но вы можете уменьшить количество обращений к джедаям, выполнив Set<String> keys = jedis.keys(pattern); jedis.del(keys.toArray(new String[keys.size()])); - person dbaq; 18.04.2017

KEYS не рекомендуется использовать из-за его неэффективности при использовании в продакшене. См. https://redis.io/commands/keys. Вместо этого лучше использовать SCAN. Кроме того, более эффективный вызов, чем повторные вызовы jedis.del(), состоит в том, чтобы сделать один вызов jedis для удаления совпадающих ключей, передав массив ключей для удаления. Более эффективное решение представлено ниже:

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()]));
}
person Aprille    schedule 09.03.2017
comment
Меня интересуют две вещи: почему KEYS настолько неэффективны, и действительно ли SCANning нетривиальных записей (скажем, 10kb JSON) более эффективен, чем использование KEYS. Я имею в виду - ключи в основном похожи на SCAN, только сбрасывают содержимое и возвращают одним скопом. Что вам нужно сделать здесь в любом случае. - person Ondra Žižka; 30.01.2018
comment
Поскольку Redis обычно считается однопоточным, команда KEYS может блокироваться на несколько секунд, если набор достаточно велик. Во многих производственных средах ожидание даже пары миллисекунд может вызвать серьезные проблемы с производительностью, поскольку предполагается, что Redis работает быстро. - person Kirk Backus; 05.06.2018

Попробуйте использовать eval. Я не эксперт Lua, но этот код работает.

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);
    }
  }
}

А затем позвоните:

deleteKeys("temp:keys:*");

Это гарантирует один вызов на стороне сервера, множественную операцию удаления.

person corindiano    schedule 03.05.2014

Вы можете сделать это с помощью Redisson в одну строку:

redisson.getKeys().deleteByPattern(pattern)
person Nikita Koksharov    schedule 29.11.2015

Вы можете сделать это с помощью bash:

$ redis-cli KEYS "sample_pattern:*" | xargs redis-cli DEL
person Agis    schedule 23.01.2014
comment
извините, забыл упомянуть, что я хочу сделать это в коде Java. но это полезно. - person iCodeLikeImDrunk; 23.01.2014
comment
@yaojiang Я никогда не писал ни строчки на Java, но вот что я думаю, см. обновленный ответ. - person Agis; 23.01.2014
comment
нет кости. похоже, что реализация jedis позволяет мне делать только что-то вроде jedis.del(key1, key2, key3,...); - person iCodeLikeImDrunk; 24.01.2014
comment
@yaojiang О, я думал, что jedis.keys() вернет набор ключей. Что он возвращает, кстати? - person Agis; 24.01.2014
comment
один или несколько строковых аргументов или byte[]. - person iCodeLikeImDrunk; 24.01.2014