【问题标题】:Jedis/Redis SocketTimeout exception on Lua scriptsLua 脚本上的 Jedis/Redis SocketTimeout 异常
【发布时间】:2016-10-08 04:39:49
【问题描述】:

我们正在使用 lua 脚本来批量删除数据库更新时的数据。 Jedis 使用管道执行 lua 脚本。

local result = redis.call('lrange',key,0,12470)
for i,k in ipairs(result) do
   redis.call('del',k)
   redis.call('ltrim',key,1,k)
end

try (Jedis jedis = jedisPool.getResource()) {
        Pipeline pipeline = jedis.pipelined();
        long len = jedis.llen(table);
         String script = String.format(DELETE_LUA_SCRIPT, table, len);
    LOGGER.info(script);
    pipeline.eval(script);
    pipeline.sync();
    } catch (JedisConnectionException e) {
        LOGGER.info(e.getMessage());
    }

对于大范围,我们注意到 lua 脚本速度变慢并且我们得到 SocketTimeOutExceptions。

运行 redis-cli slowlog 只显示执行时间过长的 lua 脚本。

有没有更好的方法来做到这一点?我的 lua 脚本被阻塞了吗?

当我只使用管道进行批量删除时,慢日志也会返回慢查询。

try (Jedis jedis = jedisPool.getResource()) {
        Pipeline pipeline = jedis.pipelined();
        long len = jedis.llen(table);
        List<String> queriesContainingTable = jedis.lrange(table,0,len);
        if(queriesContainingTable.size() > 0) {
            for (String query: queriesContainingTable) {
                pipeline.del(query);
                pipeline.lrem(table,1,query);
            }
            pipeline.sync();
        }
    } catch (JedisConnectionException e) {
        LOGGER.info("CACHE INVALIDATE FAIL:"+e.getMessage());
    }

【问题讨论】:

    标签: lua redis jedis


    【解决方案1】:

    slowlog 能够单独存储前 128 个慢日志(可以在 redis.conf slowlog-max-len 128 中更改)。因此,您使用 LUA 脚本的第一个模型肯定是一个阻塞模型。

    如果您将这样一个数字(12470)一一删除,它肯定是一个阻塞数字,因为它需要更多时间才能完成。在 2 个模型中,第 2 个对我来说很好(使用管道),因为您避免了迭代,您所做的只是点击 del 查询 n 次。

    您可以对每 100 或 1000 个键使用 del 多个键(在小测试后您认为最佳)。您可以将它们完全分组到一个管道中。

    或者,如果您可以在没有原子性的情况下执行相同操作,则可以在循环中一次删除每 100 或 1000 个键,这样就不会成为阻塞调用。

    尝试使用不同的组合获取指标并使用优化的组合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 2020-01-10
      • 2014-04-09
      • 1970-01-01
      • 2019-05-28
      • 2020-11-08
      • 1970-01-01
      相关资源
      最近更新 更多