redis - 如何以安全的方式 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)
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 流中删除或删除给定数量的条目的单独问题的更多详细信息?
推荐阅读
- python - Python - 通过匹配/比较来自多个数据帧的变量来计算两个日期之间发生的记录数
- python - TOML vs YAML vs StrictYAML
- java - 如何在java中实现自定义的电子表格公式字段?
- java - 如何按名称获取 Spring bean
- c - 为什么我用 C 编写的计算器不能工作?
- azure-active-directory - 如何使用 Graph REST API 对个人 OneDrive 进行身份验证
- css - Bootstrap 4 组宽度:100%;到具有“容器”类的 div 项的子项
- c - 如何在 gcc 中使用 Decimal64 DPD
- flutter - 如何使用flutter HookWidget访问didChangeAppLifecycleState生命周期钩子中的上下文?
- multithreading - 过去 5 秒内没有活动或错过太多心跳 [RabbitMQ]