如何以安全的方式进行 Xtrim(修剪 redis 流)



Redis Xtrim 是保留一些记录并删除旧的记录。

假设我有 100 条记录,我想保留最新的 10 条记录。(假设Java/scala API(

redis = new Jedis(...)
redis.xlen("mystream") // returns 100
// new records arrive stream at here
redis.xtrim("mystream", 10)

但是,在执行xlenxtrim之间到达新记录。例如,现在有 105 条记录,它将保留 95 - 105,但是我想从 90 开始。所以它也修剪了 90 - 95,这很糟糕。

有什么想法吗?

选项 1:如果您总是只想保留 10 个最新的,请使用:

XADD mystream MAXLEN 10 * field value ...

通过将修剪移动到添加,您可以将其始终保持在 10。您可以忘记要修剪的单独逻辑。

在绝地武士中,

xadd(String key, StreamEntryID id, Map<String,String> hash, long maxLen, boolean approximateLength)

选项2:乐观,使用交易。

WATCH mystream 
XLEN mystream
MULTI
XTRIM mystream MAXLEN 10
EXEC

在这里,如果流已被修改,事务将失败,EXEC返回 null,然后重试。

杰迪斯交易示例

选项 3:

使用 Lua 脚本调整XTRIM目标数字。有了这个,您可以执行XLEN,按照逻辑来决定您想要的修剪,然后执行XTRIM,所有 Redis 服务器端,原子,因此您的流没有机会在两者之间发生变化。

这里有一些绝地武士的评估例子。

更新:

像下面这样的Lua脚本应该可以解决问题:原子地评估当前myStreams条目的数量,然后相应地调用XTRIM。

EVAL "local streamLen = redis.call('XLEN', KEYS[1]) n if streamLen >= tonumber(ARGV[1]) then n return redis.call('XTRIM', KEYS[1], 'MAXLEN', streamLen - tonumber(ARGV[1])) n else return redis.error_reply(KEYS[1]..' has less than '..ARGV[1]..' items') end" 1 myStream 90

让我们来看看 Lua 脚本:

local streamLen = redis.call('XLEN', KEYS[1])
if streamLen >= tonumber(ARGV[1]) then 
return redis.call('XTRIM', KEYS[1], 'MAXLEN', streamLen - tonumber(ARGV[1]))
else
return redis.error_reply(KEYS[1]..' has less than '..ARGV[1]..' items')
end

我发布了有关如何从 Redis 流中删除或删除给定数量的条目的单独问题的更多详细信息?

最新更新