脚本管理

除了SCRIPT LOAD命令之外,Redis还提供了SCRIPT EXISTS、SCRIPT FLUSH和SCRIPT KILL这3个命令来管理脚本以及脚本缓存,本节接下来 将分别对这3个命令进行介绍。

SCRIPT EXISTS:检查脚本是否已被缓存

SCRIPT EXISTS命令接受一个或多个SHA1校验和作为参数,检查这些校验和对应的脚本是否已经被缓存到了服务器中:

SCRIPT EXISTS sha1 [sha1 ...]

当某个校验和对应的脚本已经被缓存时,命令返回1;相反,如果校验 和对应的脚本尚未被缓存,那么命令返回0。

以下代码展示了SCRIPT EXISTS命令的使用方法:

redis> SCRIPT LOAD "return 10086" -- 载入两个脚本
"a9b6689bf0d2962188a5fb8f2502e8de5a19fc26"
redis> SCRIPT LOAD "return 'hello world'"
"5332031c6b470dc5a0dd9b4bf2030dea6d65de91"
redis> SCRIPT EXISTS "a9b6689bf0d2962188a5fb8f2502e8de5a19fc26" "5332031c6b470dc5a0dd9b4bf2030de
a6d65de91" "not-exists-sha1-123456789abcdefghijklmno"
1) (integer) 1 -- 脚本存在
2) (integer) 1 -- 脚本存在
3) (integer) 0 -- 脚本不存在

其他信息

  • 复杂度:O(N),其中N为用户输入的校验和数量。

  • 版本要求:SCRIPT EXISTS命令从Redis 2.6.0版本开始可用。

SCRIPT FLUSH:移除所有已缓存脚本

执行SCRIPT FLUSH命令将移除服务器已缓存的所有脚本,这个命令一般只会在调试时使用:

SCRIPT FLUSH

命令在成功移除所有已缓存脚本之后会返回OK作为回复。

以下是一个使用SCRIPT FLUSH命令的例子:

redis> SCRIPT LOAD "return 10086" -- 载入两个脚本
"a9b6689bf0d2962188a5fb8f2502e8de5a19fc26"
redis> SCRIPT LOAD "return 'hello world'"
"5332031c6b470dc5a0dd9b4bf2030dea6d65de91"
redis> SCRIPT EXISTS "a9b6689bf0d2962188a5fb8f2502e8de5a19fc26" "5332031c6b470dc5a0dd9b4bf2030de
a6d65de91"
1) (integer) 1 -- 脚本存在
2) (integer) 1
redis> SCRIPT FLUSH -- 移除所有已载入的脚本
OK
redis> SCRIPT EXISTS "a9b6689bf0d2962188a5fb8f2502e8de5a19fc26" "5332031c6b470dc5a0dd9b4bf2030de
a6d65de91"
1) (integer) 0 -- 脚本不再存在
2) (integer) 0

其他信息

  • 复杂度:O(N),其中N为被移除脚本的数量。

  • 版本要求:SCRIPT FLUSH命令从Redis 2.6.0版本开始可用。

SCRIPT KILL:强制停止正在运行的脚本

因为Lua脚本在执行时会独占整个服务器,所以如果Lua脚本的运行时 间过长,又或者因为编程错误而导致脚本无法退出,那么就会导致其 他客户端一直无法执行命令。

配置选项lua-time-limit的值定义了Lua脚本可以不受限制运行的时 长,这个选项的默认值为5000:

lua-time-limit <milliseconds>

当脚本的运行时间低于lua-time-limit指定的时长时,其他客户端发 送的命令请求将被阻塞;相反,当脚本的运行时间超过lua-timelimit指定的时长时,向服务器发送请求的客户端将得到一个错误回 复,提示用户可以使用SCRIPT KILL或者SHUTDOWN NOSAVE命令来终止 脚本或者直接关闭服务器。

举个例子,如果我们使用客户端client-1,在Lua脚本中执行以下这个无限循环:

client-1> EVAL "repeat until false" 0

然后在脚本运行超过lua-time-limit指定的时长之后,使用另一个客 户端client-2向服务器发送命令请求,那么服务器将向客户端返回以 下错误信息,表示自己正忙于执行Lua脚本,无法执行其他命令请求:

client-2> SET msg "hello, Redis?"
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

为了让用户可以在有需要时手动终止正在运行的Lua脚本,并让服务器 回归正常状态,Redis提供了以下命令:

SCRIPT KILL

当Lua脚本的运行时间超过了lua-time-limit指定的时限时,用户就可 以使用客户端向服务器发送SCRIPT KILL命令,尝试终止正在运行的 Lua脚本。

用户在执行SCRIPT KILL命令之后,服务器可能会有以下两种反应:

  • 如果正在运行的Lua脚本尚未执行过任何写命令,那么服务器将终止该脚本,然后回到正常状态,继续处理客户端的命令请求。

  • 如果正在运行的Lua脚本已经执行过写命令,并且因为该脚本尚未执 行完毕,所以它写入的数据可能是不完整或者错误的,为了防止这些 脏数据被保存到数据库中,服务器是不会直接终止脚本并回到正常状 态的。在这种情况下,用户只能使用SHUTDOWN nosave命令,在不执行 持久化操作的情况下关闭服务器,然后通过手动重启服务器来让它回 到正常状态。

作为例子,以下代码展示了SCRIPT KILL命令成功终止Lua脚本的情形:

redis> SET msg "hello, Redis?" -- 有脚本仍在运行
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
redis> SCRIPT KILL
OK -- 返回OK表示已经成功终止脚本
redis> SET msg "hello, Redis?"
OK -- 现在服务器可以如常执行命令请求了

而以下代码则展示了SCRIPT KILL命令无法终止Lua脚本,只能通过 SHUTDOWN nosave命令来关闭服务器的情形:

redis> SCRIPT KILL
(error) UNKILLABLE Sorry the script already executed write commands against the
dataset. You can either wait the script termination or kill the server in a hard way using the S
HUTDOWN NOSAVE command.
redis> SHUTDOWN nosave
not connected> -- 服务器已被关闭

其他信息

  • 复杂度:O(1)。

  • 版本要求:SCRIPT KILL命令从Redis 2.6.0版本开始可用。