Jedis/Redis Lua 个脚本的 SocketTimeout 异常
Jedis/Redis SocketTimeout exception on Lua scripts
我们正在使用 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 也 returns 慢查询。
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());
}
slowlog 能够单独存储前 128 个慢日志(可以在 redis.conf slowlog-max-len 128 中更改)。因此,您使用 LUA 脚本的第一个模型肯定是一个阻塞模型。
如果你把这样一个号码(12470)一个一个地删除,肯定是阻塞的,因为它需要更多的时间才能完成。在 2 个模型中,第 2 个对我来说很好(使用管道),因为你避免了迭代,你所做的就是点击 del 查询 n 次。
您可以对每 100 或 1000 个键使用多个键的删除(经过小型测试后您认为最佳)。您可以将它们一起组合到一个管道中。
或者如果你可以在没有原子性的情况下做同样的事情,你可以在一个循环中一次删除每 100 或 1000 个键,这样它就不会成为阻塞调用。
尝试不同的组合,采用指标并使用优化的指标。
我们正在使用 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 也 returns 慢查询。
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());
}
slowlog 能够单独存储前 128 个慢日志(可以在 redis.conf slowlog-max-len 128 中更改)。因此,您使用 LUA 脚本的第一个模型肯定是一个阻塞模型。
如果你把这样一个号码(12470)一个一个地删除,肯定是阻塞的,因为它需要更多的时间才能完成。在 2 个模型中,第 2 个对我来说很好(使用管道),因为你避免了迭代,你所做的就是点击 del 查询 n 次。
您可以对每 100 或 1000 个键使用多个键的删除(经过小型测试后您认为最佳)。您可以将它们一起组合到一个管道中。
或者如果你可以在没有原子性的情况下做同样的事情,你可以在一个循环中一次删除每 100 或 1000 个键,这样它就不会成为阻塞调用。
尝试不同的组合,采用指标并使用优化的指标。