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

Aar*_*esh 4 lua eval redis

我尝试执行以下错误的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
Run Code Online (Sandbox Code Playgroud)

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

(error) Lua redis() command arguments must be strings or integers
Run Code Online (Sandbox Code Playgroud)

此错误不会传达redis.call()和redis.pcall()之间的区别,如文档所示

"redis.call()类似于redis.pcall(),唯一的区别是如果Redis命令调用将导致错误,redis.call()将引发Lua错误,反过来将强制EVAL返回命令调用程序出错,而redis.pcall将捕获错误,返回表示错误的Lua表."

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

cat*_*ell 13

这是一个棘手的情况,因为在你示例命令不产生错误,使用的是redis.callredis.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)
Run Code Online (Sandbox Code Playgroud)

但是,您可能会注意到我没有返回结果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
Run Code Online (Sandbox Code Playgroud)

有了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"
Run Code Online (Sandbox Code Playgroud)