说明 redis.call() 和 redis.pcall() 之间的区别



我尝试执行以下错误的 eval 命令来理解 redis.call() 和 redis.pcall() 之间的区别

eval "return redis.call(ARGV[2],KEYS[1])" 1 key get   
eval "return redis.pcall(ARGV[2],KEYS[1])" 1 key get

在这两种情况下,我都得到了下面的错误,

(error) Lua redis() command arguments must be strings or integers

此错误并没有传达 redis.call() 和 redis.pcall() 之间的区别,如文档所示,该文档指出

" redis.call() 类似于 redis.pcall(

),唯一的区别是,如果 Redis 命令调用会导致错误,redis.call() 将引发一个 Lua 错误,进而强制 EVAL 向命令调用者返回错误,而 redis.pcall 将捕获返回表示错误的 Lua 表的错误。

所以根据文档,在使用redis.pcall()的情况下,应该捕获错误,对吧!在这种情况下,为什么两个错误相同?如果我误解了差异,最好有人能清楚地说明命令之间的差异!!

这是一个

棘手的情况,因为在示例中,该命令不会生成错误,您redis.call使用不正确redis.pcall(因为ARGV[2]就像错误消息告诉您的那样nil)。因此,在这两种情况下,错误都不会恢复。

下面是命令实际失败的示例,您可以看到差异:

redis 127.0.0.1:6379> set foo bar
OK
redis 127.0.0.1:6379> eval 'redis.call("hget","foo","bar")' 0
(error) ERR Error running script (call to f_9e6d82f0740926e0a70775430bda59a54d4e0664): ERR Operation against a key holding the wrong kind of value
redis 127.0.0.1:6379> eval 'redis.pcall("hget","foo","bar")' 0
(nil)

但是,您可能会注意到我没有返回 pcall 的结果,因此脚本返回 nil 。如果我返回错误命令的结果怎么办?

redis 127.0.0.1:6379> eval 'return redis.call("hget","foo","bar")' 0
(error) ERR Error running script (call to f_d0a8dce7264708876edf262052788fc90a8e8325): ERR Operation against a key holding the wrong kind of value
redis 127.0.0.1:6379> eval 'return redis.pcall("hget","foo","bar")' 0
(error) ERR Operation against a key holding the wrong kind of value

有了call什么都没有改变,因为错误(把它想象成其他语言中的异常 - Java,Python等)在函数有机会返回之前就被抛出。

但是,对于pcall,函数调用会返回一个带有单个err字段的表,该表由 Redis 转换为"错误回复",因此您看不到它。你怎么能检查呢?线性化它!

redis 127.0.0.1:6379> eval 'local t = redis.pcall("hget","foo","bar"); local r = {type(t)}; for k,v in pairs(t) do r[#r+1] = k; r[#r+1] = v; end; return r' 0
1) "table"
2) "err"
3) "ERR Operation against a key holding the wrong kind of value"

它失败,因为 Redis 无法执行调用或 pcall 命令。我的意思是它在执行实际的 Redis 命令(这里是一个 get 命令)之前失败。pcall 将在执行 Redis 命令期间捕获错误,而不是在执行 pcall 本身期间捕获错误。

让我们修改您的输入,以便 Redis 命令失败(而不是 redis.call 命令本身)。

> EVAL "return redis.call(ARGV[1],KEYS[1])" 1 key get
"100"
> EVAL "return redis.call(ARGV[1],KEYS[1])" 1 key born_to_fail
(error) ERR Error running script (call to f_2673dc91ae540aa65dedd262a952d5338e330b37): @user_script:1: @user_script: 1: Unknown Redis command called from Lua script
> EVAL "return redis.pcall(ARGV[1],KEYS[1])" 1 key born_to_fail
(error) @user_script: 1: Unknown Redis command called from Lua script

您可以在第二次调用时看到 Redis 错误导致 Lua 错误。

在第三次调用中,改用 pcall,因此结果不再是 Lua 错误,而只是一个包含错误文本的输出字符串。

最新更新