Redis中的EVAL是否真的具有原子性和崩溃安全性?

Redis文档似乎确认EVAL脚本类似于MULTI/EXEC事务。

用我的个人话来说,这意味着LUA脚本有两个保证:

  • 顺序执行:LUA脚本像单独在服务器上运行一样,这对我来说没问题
  • 原子/一次性写入:这我不太理解LUA脚本。什么时候会调用"EXEC like"?因为使用脚本可以根据读取(甚至写入,因为一些写入函数会返回值,如NX函数)做有条件的写入。那么Redis如何保证脚本执行的是全部或什么都不执行?如果服务器在脚本运行期间崩溃会发生什么?Redis无法进行回滚。

(我对于MULTI/EXEC在这个第二点上没有这个顾虑,因为在MULTI/EXEC中你不能根据之前的命令进行写入。)

(对于基础英语,我很抱歉,我是法国人)

点赞
用户4406961
用户4406961

我刚刚用了这个非常缓慢的脚本进行了测试:

eval "redis.call('set', 'hello', 10); for i = 1, 1000000000 do redis.call('set', 'test', i) end" 0

^ 这将 hello 键设置为 10,然后无限制地将 test 键设置为一个数字。

执行脚本时,Redis 记录了以下警告:

# Lua slow script detected: still in execution after 5194 milliseconds. You can try killing the script using the SCRIPT KILL command. Script SHA1 is: ...

因此,我测试了在脚本执行时完全关闭容器以模拟崩溃的情况。

重启后,hellotest 键都为 nil,这意味着没有执行任何已调用的命令。因此,脚本确实是原子和崩溃安全的,就像文档中所述一样。

我认为 Redis 在 MULTI/EXEC 中包装了 Lua 脚本以使它们具有原子性,或者至少有相同的效果。

2021-12-02 14:43:51