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)
但是,在执行xlen
和xtrim
之间到达新记录。例如,现在有 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 流中删除或删除给定数量的条目的单独问题的更多详细信息?