事务文档中表示:
"我们可能会废弃和最终删除事务"和"你可以通过脚本完成Redis事务能做的所有事情"
http://redis.io/topics/transactions
但是这真的是这样吗?我看到了一个问题。
在事务中,您可以监视多个变量、读取这些变量,并基于这些变量的唯一状态在调用 EXEC 之前进行完全不同的写入。如果在介入时间内有任何干扰这些变量的状态,EXEC 将不执行事务。(这使您可以重试它。这是一个完美的事务系统。)
然而,EVAL 脚本则不能这样。根据此页面上的文档:
"脚本作为纯函数...无论何时,给定相同的输入数据集,脚本始终以相同的参数评估相同的 Redis 写命令。脚本执行过程中或在不同的脚本执行之间,所进行的操作都不能依赖于任何可能随着脚本执行进展或在脚本执行之间更改的隐藏(非显式)信息或状态,也不能依赖于来自 I/O 设备的任何外部输入。"
我对 EVAL 的问题在于您无法在脚本内 GET 这些变量的状态,并基于这些变量的状态进行独特的写操作。再次强调:"脚本始终以相同的参数评估相同的 Redis 写命令,给定相同的输入数据集。"因此,结果写入已经确定(从第一次运行缓存),而且 EVAL 脚本不关心脚本内 GET 值是什么。您唯一能做的就是在调用 EVAL 之前对那些变量执行 GET,然后将这些变量传递给 EVAL 脚本,但这里有一个问题:现在您在调用 GET 和调用 EVAL 之间存在原子性问题。
换句话说,在 EVAL 中,您需要获取那些您本来会为事务进行 WATCH 的所有变量,然后将它们传递给 EVAL 脚本。由于脚本的原子性直到实际启动脚本才得到保证,并且在调用 EVAL 启动脚本之前需要获取这些变量,因此在获取变量和将它们传递给 EVAL 之间留下了一个空隙,其中这些变量的状态可能会发生变化。因此,对于一组非常重要的用例,您在使用 WATCH 时拥有的原子性保证在使用 EVAL 时是不存在的。那么为什么会谈论弃用事务,这将导致重要的 Redis 功能丧失呢?还是说有一种我尚未理解的使用 EVAL 脚本的方法?或者计划推出的功能可以解决 EVAL 的问题?(假设性的例子:如果他们使 WATCH 与 EXEC 以相同的方式工作,则可能有效。)
这个问题有解决方案吗?还是我应该理解 Redis 在长期内可能并非完全安全的事务处理?