交易文件说:
“我们可能会弃用并最终删除交易”和“你可以用 Redis 交易做的一切,你也可以用脚本做”
http://redis.io/topics/transactions
但真的吗?我看到了这个问题。
在一个事务中,您可以观察多个变量,读取这些变量,并且根据这些变量的独特状态,您可以在调用 EXEC 之前进行一组完全不同的写入。如果在中间时间有任何干扰这些变量的状态,EXEC 将不会执行事务。(这允许您重试。这是一个完美的交易系统。)
EVAL 脚本不会让您这样做。根据此页面上的文档:
“脚本作为纯函数......在给定相同的输入数据集的情况下,脚本始终评估具有相同参数的相同 Redis 写入命令。脚本执行的操作不能依赖于任何隐藏(非显式)信息或可能随着脚本而改变的状态执行继续或在脚本的不同执行之间进行,也不能依赖于来自 I/O 设备的任何外部输入。”
我在 EVAL 中看到的问题是您无法在脚本中获取这些变量的状态,并根据这些变量的状态进行一组独特的写入。再说一遍:“在给定相同的输入数据集的情况下,该脚本始终使用相同的参数评估相同的 Redis 写入命令。” 因此,生成的写入已经确定(从第一次运行开始缓存),并且 EVAL 脚本不关心脚本中的 GET 值是什么。您唯一能做的就是在调用 EVAL 之前对这些变量执行 GET,然后将这些变量传递给 EVAL 脚本,但问题是:现在调用 GET 和调用 EVAL 之间存在原子性问题。
换句话说,所有你会为事务执行 WATCH 的变量,在 EVAL 的情况下,你需要获取这些变量,然后将它们传递给 EVAL 脚本。由于在脚本实际启动之前无法保证脚本的原子性质,并且您需要在调用 EVAL 启动脚本之前获取这些变量,这留下了一个开口,这些变量的状态可能会在 GET 和传递它们之间发生变化评估。因此,对于一组非常重要的用例,您在 WATCH 中所拥有的原子性保证是在 EVAL 中所没有的。
那么,为什么要讨论弃用事务,因为这会导致重要的 Redis 功能丢失?或者实际上有没有办法用我还不理解的 EVAL 脚本来做到这一点?或者是否有计划为 EVAL 解决这个问题的功能?(假设的例子:如果他们让 WATCH 与 EVAL 一起工作,就像 WATCH 与 EXEC 一样,那可能会奏效。)
有针对这个的解决方法吗?或者我是否理解 Redis 从长远来看可能不是完全安全的交易?