Lua脚本上的Jedis / Redis SocketTimeout异常

时间:2016-06-08 04:56:26

标签: lua redis jedis

我们正在使用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脚本阻止?

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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