【问题标题】:Redis/Jedis - Delete by pattern?Redis/Jedis - 按模式删除?
【发布时间】:2014-02-14 13:14:23
【问题描述】:

通常,我获取键集,然后使用查找删除每个键/值对。

是否可以通过模式删除所有键?

即:

Del sample_pattern:*

【问题讨论】:

    标签: java redis jedis del


    【解决方案1】:

    对于 Jedis 来说,“按模式删除”似乎基本上是获取特定模式的所有键,然后循环遍历它。

    Set<String> keys = jedis.keys(pattern);
    for (String key : keys) {
        jedis.del(key);
    } 
    

    【讨论】:

    • 扫描更好。但是你可以通过Set&lt;String&gt; keys = jedis.keys(pattern); jedis.del(keys.toArray(new String[keys.size()]));来减少对jedis的调用次数
    【解决方案2】:

    不建议使用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()]));
    }
    

    【讨论】:

    • 我想知道为什么 KEYS 如此无效,以及扫描非平凡条目(例如 10kb JSON)是否真的比使用 KEYS 更有效。我的意思是 - 键基本上就像 SCAN,只是删除内容并批量返回。无论如何,你需要在这里做。
    • 由于 Redis 通常被认为是单线程的,如果集合足够大,KEYS 命令可能会阻塞几秒钟。在许多生产环境中,即使等待几毫秒也可能导致严重的性能问题,因为 Redis 被假定为很快。
    【解决方案3】:

    您应该尝试使用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:*");
    

    这保证了一次服务器端调用,多次删除操作。

    【讨论】:

      【解决方案4】:

      您可以在一行中使用Redisson

      redisson.getKeys().deleteByPattern(pattern)
      

      【讨论】:

        【解决方案5】:

        你可以用 bash 做到这一点:

        $ redis-cli KEYS "sample_pattern:*" | xargs redis-cli DEL
        

        【讨论】:

        • 抱歉,忘了说我想在 Java 代码中执行此操作。但这很有用。
        • @yaojiang 我从来没有写过一行Java,但这是我的看法,请参阅更新后的答案。
        • 没有骰子。看起来绝地实现只允许我做类似 jedis.del(key1, key2, key3,...);
        • @yaojiang 哦,我以为jedis.keys() 会返回一组键。顺便说一句,它返回什么?
        • 一个或多个字符串参数,或字节[]。
        猜你喜欢
        • 2017-07-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        • 2016-02-06
        • 2014-12-16
        • 2019-03-19
        • 1970-01-01
        相关资源
        最近更新 更多