Redis:Lua脚本为什么要替换事务?

问题描述 投票:14回答:3

交易文档说:

“我们可能会弃用并最终删除交易”和“一切可以处理Redis事务,也可以处理脚本“

http://redis.io/topics/transactions

但是吗?我认为有问题。

在事务中,您可以监视多个变量,读取这些变量,并且基于这些变量的唯一状态,可以在调用EXEC之前进行完全不同的写操作。如果在此期间有任何因素干扰这些变量的状态,则EXEC将不会执行该事务。 (允许您重试。这是一个完美的交易系统。)

EVAL脚本将不允许您这样做。根据此页面上的文档:

“脚本作为纯函数...该脚本始终求值相同在给定相同输入数据的情况下,Redis用相同的参数编写命令组。脚本执行的操作不能依赖于任何隐藏的(非明确的)信息或状态可能会随着脚本而改变执行继续进行或在脚本的不同执行之间执行,也不是否可以取决于I / O设备的任何外部输入。“

http://redis.io/commands/eval

我在EVAL中看到的问题是,您无法在脚本内获取这些变量的状态,并且无法基于这些变量的状态进行唯一的一组写操作。再次:“在给定相同输入数据集的情况下,脚本始终使用相同的参数评估相同的Redis写入命令。”因此,已经确定了写入结果(从第一次运行开始缓存),并且EVAL脚本不在乎该脚本中的GET值是什么。您唯一能做的就是在调用EVAL之前对这些变量执行GET,然后将这些变量传递给EVAL脚本,但这是问题所在:现在,在调用GET和调用EVAL之间存在原子性问题。

换句话说,您将为事务完成WATCH的所有变量,对于EVAL,则需要获取这些变量,然后将其传递给EVAL脚本。由于直到脚本真正启动之前,脚本的原子性才能得到保证,因此您需要在调用EVAL启动脚本之前获取那些变量,这为这些变量的状态可能在GET和传递它们之间发生变化提供了一个空缺。到EVAL。因此,对于一组非常重要的用例,WATCH所没有的原子性保证就与EVAL所没有的保证。

那么为什么要谈论过时的事务而导致重要的Redis功能丢失呢?还是实际上有一种方法可以使用我尚不了解的EVAL脚本来做到这一点?还是有计划中的功能可以解决此问题? (一个假设的示例:如果他们使WATCH与EVAL一起使用,与WATCH与EXEC一起使用的方式一样,则可能会起作用。)

有解决方案吗?还是我了解Redis从长远来看可能并不完全安全?

redis
3个回答
19
投票

确实,lua脚本可以完成任何事务,但是我认为Redis事务不会消失。


14
投票

EVAL脚本实​​际上扩展并简化了交易功能。


0
投票
EVAL脚本可以完成事务可以做的所有事情,除了乐观锁定,这在单线程环境中不是很有用。
© www.soinside.com 2019 - 2024. All rights reserved.