local function scriptNoRollback(keys)
redis.call("INCR", keys[1])
redis.call("INCR", keys[2])
return "OK"
end
local function scriptRollback(keys)
-- Store initial value.
local initValueCounter1 = redis.call("GET", keys[1])
redis.call("INCR", keys[1])
local reply = redis.pcall("INCR", keys[2])
if type(reply) == "table" and reply["err"] ~= nil then
reply["err"] = "Oops, error!"
-- Try to rollback data.
redis.call("SET", keys[1], initValueCounter1)
return reply
end
return "OK"
end
127.0.0.1:6379> MSET counter1 1 counter2 A
OK
127.0.0.1:6379> FCALL scriptNoRollback 2 counter1 counter2
(error) ERR value is not an integer or out of range script: scriptNoRollback, on @user_function:118.
127.0.0.1:6379> MGET counter1 counter2
1) "2"
2) "A"
3条答案
按热度按时间osh3o9ms1#
在Redis中,Lua脚本是以原子方式执行的。这意味着要么整个脚本都成功执行,要么一个都没有执行。如果Lua脚本没有返回值,(例如,由于脚本中的错误或异常),事务将不会部分应用,Redis服务器将不会提交脚本所做的任何更改。您对回滚操作的预期是正确的。**
在您提供的Lua脚本中,如果在执行过程中出现错误,没有返回newBalance,Redis服务器会确保该事务不被应用,并且不会对Redis数据库中的数据进行任何更改。
这种原子行为是Redis脚本的基本特性,在Lua脚本中执行多步操作时,可以保证数据的一致性和完整性。如果脚本出错,Redis数据存储不会发生任何变化,数据库保持一致状态。
eivnm1vs2#
不可以,在Redis Lua脚本中没有自动回滚transactions。如果脚本稍后出现故障,执行的命令不会回滚。实际上,Redis中根本不存在回滚。
但是有discussions关于实现某种回滚特性。
“原子地”的重要definition:
Redis保证脚本的原子执行。在执行脚本时,所有服务器活动在整个运行期间都被阻止。
这意味着Redis将整个脚本视为一个操作,没有其他操作中断它。
为了防止错误,你应该在使用之前对所有的输入参数进行彻底的验证。为了处理潜在的错误,你可以使用
redis.pcall()
而不是redis.call()
。使用redis.pcall()
,你可以处理Redis引发的运行时错误,因为redis.pcall()
总是返回一个回复,而不会抛出一个运行时异常。这对创建你自己的回滚逻辑和记录错误很有帮助。范例:
字符串
scriptNoRollback
正常:型
scriptNoRollback
错误:型
counter1
不会回滚到初始状态。scriptRollback
正常:型
scriptRollback
错误:型
counter1
回滚到初始状态。eoxn13cs3#
在Redis中,Lua脚本不支持关系数据库管理系统(RDBMS)中的传统事务。Redis没有内置支持具有回滚功能的多语句事务(如RDBMS系统中的ACID事务)。
您提供的Lua脚本是一个原子操作,这意味着它要么完全成功,要么完全失败。它不是传统数据库意义上的事务,并且它没有失败时回滚的概念。
在Lua脚本中,如果发生错误(例如,由于参数无效或Redis服务器问题),脚本不会返回值,Java应用程序也不会收到响应。但是,它不会触发以前的Redis操作回滚。
如果你在Redis中需要类似transaction的行为,可以使用Redis内置的MULTI/EXEC transaction机制。你可以使用MULTI将多个命令排队,然后使用EXEC原子地执行它们。如果任何一个命令失败,整个transaction都会回滚。但是Lua脚本本身并不参与这种transaction机制。
总而言之,你的Lua脚本并没有提供类似transaction-like的回滚行为。如果你想确保Redis中的transactions,你应该使用MULTI/EXEC机制,而不是仅仅依靠Lua脚本。