3.3 开发规范与命令兼容
3.3.2 Lua 脚本规范
Lua是一种脚本语言,目的是为了嵌入应用程序中,为应用程序提供灵活的扩展和定制 功能。GaussDB(for Redis)使用的是Lua5.1.5版本,与开源Redis5.0使用的Lua版本是 一致的。
与开源 Redis Lua 的区别
1. EVAL/EVALSHA命令
命令格式:
EVAL script numkeys key [key …] arg [arg …]
EVALSHA sha1 numkeys key [key …] arg [arg …]
上述命令的语法与操作与开源Redis一致。用户需自己保证将脚本中使用到的 Redis key显式的通过key参数传入,而不是直接在脚本中编码,并且如果带有多 个key参数,则要求所有的key参数必须拥有相同的hash tag。
如果不遵循上述约束,则在Lua中执行涉及这些key的Redis操作时,可能会返回类 似“partition not found”的错误信息。
2. SCRIPT命令
SCRIPT命令包含了一组管理Lua脚本的子命令,具体可以通过SCRIPT HELP命令查 询具体的操作。
SCRIPT大部分命令都与开源Redis兼容,其中需要特别说明的命令如下:
– SCRIPT KILL
GaussDB(for Redis)是多线程执行的环境,允许同时执行多个Lua脚本,执行 SCRIPT KILL,会终止所有正在运行的Lua脚本。
为了方便使用,GaussDB(for Redis)扩展了SCRIPT KILL命令,用户可以通过
‘SCRIPT KILL SHA1’来终止指定哈希值的脚本。若同一时间存在多个节点 在执行哈希值相同的脚本,那么这些脚本都会被终止。
另外,由于用户无法设置Lua超时时间(config set lua-time-limit),因此在 任意时刻执行SCRIPT KILL都能直接终止脚本,而不是等待脚本超时后才终 止。
– SCRIPT DEBUG
目前GaussDB(for Redis)不支持DEBUG功能,所以该命令执行无效。
3. Lua脚本中执行Redis命令
与开源Redis一致,GaussDB(for Redis)的Lua环境中也提供了一个全局的
“redis”表,用于提供各类和Redis Server交互的函数。
如表3-7为GaussDB(for Redis)目前支持和不支持的操作列表。
表3-7 函数列表
支持的操作 不支持的操作
● redis.call()
● redis.pcall()
● redis.sha1hex()
● redis.error_reply()
● redis.status_reply()
● redis.log()
● redis.LOG_DEBUG
● redis.LOG_VERBOSE
● redis.LOG_NOTICE
● redis.LOG_WARNING
● redis.replicate_commands()
● redis.set_repl()
● redis.REPL_NONE
● redis.REPL_AOF
● redis.REPL_SLAVE
● redis.REPL_REPLICA
● redis.REPL_ALL
● redis.breakpoint()
● redis.debug()
4. Lua执行环境限制
开源Redis对Lua脚本的执行有一定的限制,比如限制脚本操作全局变量,限制随 机函数的结果,限定能够使用的系统库和第三方库等。
GaussDB(for Redis)也继承了绝大多数的限制,但是针对如下情况,GaussDB(for Redis)与开源Redis存在差异:
– Write Dirty
开源Redis规定,如果某个脚本已经执行了写操作,那么就不能被SCRIPT KILL停止执行,必须使用SHUTDOWN NOSAVE来直接关闭Redis Server。
GaussDB(for Redis)不支持执行SHUTDOWN命令,因此这条限制不会被执 行,用户仍然可以通过SCRIPT KILL来停止脚本的执行。
– Random Dirty
由于主从复制的原因,开源Redis规定,若脚本执行了带有随机性质的命令
(Time, randomkey),则不允许再执行写语义的命令。
例如,如下Lua脚本:
local t = redis.call("time")
return redis.call("set", "time", t[1]);
当该脚本的执行传递到从节点时,Time命令获取到的时间一定晚于主节点,
因此从节点执行的Set命令的值就会和主节点产生冲突。开源Redis引入了 replicate_commands来允许用户决定这种场景下的行为模式。
对于GaussDB(for Redis)来说,由于没有主从的概念,数据在逻辑上只有一 份,因此也就不存在该限制。
Lua 脚本中禁用的命令列表
目前,在Lua脚本中禁用的GaussDB(for Redis)命令列表请参见命令兼容列表。