在我的应用程序中,有一个批处理机制。它(理论上)在 redis 列表中累积项目,然后一次处理所有项目并清理(如有必要)。这是代码:
def with_private_key redis, name
return unless redis.exists name
# atomically rename to a random name, so that the batch isn't appended to.
tmpname = "temp:#{SecureRandom.hex}"
redis.rename name, tmpname
# get batch elements
batch = redis.lrange(tmpname, 0, -1).map{|b| JSON.parse(b) }
begin
# actually do something with the batch
yield batch
rescue => ex
# revert and give up
redis.rename tmpname, name
raise
else
# if there was no exception - drop the temp key, it's not needed anymore
redis.del tmpname
end
end
这是这个实现的一个小问题:有时临时键不会被删除并保留在数据库中。当我撰写这个问题时,我意识到反向重命名可能会失败,因为已经创建了新的密钥和新的批次。
那么,我应该如何改进这个算法呢?
- 就地修改批处理不起作用。LRANGE + LTRIM 对不是原子的。
- 定期检查临时键并尝试重新处理它们(命名公式必须更改为包含
app_id
,但这在这里可能并不重要)。 - 还要别的吗?也许一些 Lua 技巧(还没有使用 Lua)?
编辑:
我看到我关于重命名的理论是无效的。重命名命令:
将 key 重命名为 newkey。当源名称和目标名称相同或 key 不存在时,它会返回错误。如果 newkey 已经存在,它将被覆盖。