EVAL script numkeys key [key …] arg [arg …]
翻译 https://redis.io/commands/eval 的重要 & 值得关注的内容。
中文版地址: http://www.redis.cn/commands/eval.html
P.S. 在读这篇文章之前,我默认你已经会使用Redis的基本命令,比如SET GET,对EVAL命令也有一定了解。
redis 的第一个参数是Lua5.1脚本,这个脚本不应该定义Lua函数, 它应该就是一段Lua程序,运行在Redis服务器的上下文中。
第二个参数numkeys是后面的key的数量, 那么剩下的就是arg了。
需要注意的是: key应该是我们在Lua脚本中用到的所有的键的名称,而不是Redis键的参数则应该通过arg来传递。
这么做的原因是:所有的 Redis 命令,在执行之前都会被分析,以此来确定命令会对哪些键进行操作。所以只有正确的传递key值,才能确保分析工作正常进行。
另外一个特别重要的用途就是Redis集群情况下,可以通过key将请求发送到正确的集群节点。
我们可以使用两个不同的Lua函数从Lua脚本调用Redis命令:
- redis.call()
- redis.pcall()
他们俩不同的是,如果redis命令引发错误,call函数会引发Lua错误返回给调用者,pcall则会捕获错误并通过Lua表(table)返回。
Lua脚本能够返回返回一个值,当然它可能是一个数组(table).
当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候,命令的返回值会被转换成 Lua 数据结构。
当调用redis命令在Lua脚本返回一个值时,lua数据类型会被转换为redis协议类型,再由EVAL命令返回给客户端。
数据转换之间的规则是:当Redis类型转为Lua,再由Lua转回Redis时,这个转换所得的Redis值应该和最初的Redis值一致。
Lua类型和Redis类型之间存在着一一对应的转换关系。
Redis to Lua conversion table.
- Redis integer reply -> Lua number
- Redis bulk reply -> Lua string
- Redis multi bulk reply -> Lua table (may have other Redis data types nested)
- Redis status reply -> Lua table with a single
ok
field containing the status - Redis error reply -> Lua table with a single
err
field containing the error - Redis Nil bulk reply and Nil multi bulk reply -> Lua false boolean type
Lua to Redis conversion table.
- Lua number -> Redis integer reply (the number is converted into an integer)
- Lua string -> Redis bulk reply
- Lua table (array) -> Redis multi bulk reply (truncated to the first nil inside the Lua array if any)
- Lua table with a single
ok
field -> Redis status reply - Lua table with a single
err
field -> Redis error reply - Lua boolean false -> Redis Nil bulk reply.
- Lua boolean true -> Redis integer reply with value of 1.
P.s> 如果想从Redis返回浮点数,应该使用string类型
带宽问题:
使用EVALSHA代替EVAL,可以减少脚本传送的网络带宽消耗。
集群问题:
EVAL 的key应包含所有需要用到的key,但是在集群模式下,可能我们需要的key不在同一台机器上。
这时候EVAL命令会返回报错,简单来讲就是:集群模式下,EVAL命令几乎不可用。
不过可以通过修改Key的规则来使有关的key在同一台机器上。