Lua是一种脚本语言,目的是为了嵌入应用程序中,为应用程序提供灵活的扩展和定制功能。GeminiDB Redis使用的是Lua5.1.5版本,与开源Redis5.0使用的Lua版本是一致的。
与开源Redis Lua的区别
- 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”的错误信息。
- SCRIPT命令
SCRIPT命令包含了一组管理Lua脚本的子命令,具体可以通过SCRIPT HELP命令查询具体的操作。
SCRIPT大部分命令都与开源Redis兼容,其中需要特别说明的命令如下:
- SCRIPT KILL
GeminiDB Redis是多线程执行的环境,允许同时执行多个Lua脚本,执行SCRIPT KILL,会终止所有正在运行的Lua脚本。
为了方便使用,GeminiDB Redis扩展了SCRIPT KILL命令,用户可以通过‘SCRIPT KILL SHA1’来终止指定哈希值的脚本。若同一时间存在多个节点在执行哈希值相同的脚本,那么这些脚本都会被终止。
另外,由于用户无法设置Lua超时时间(config set lua-time-limit),因此在任意时刻执行SCRIPT KILL都能直接终止脚本,而不是等待脚本超时后才终止。
- SCRIPT DEBUG
目前GeminiDB Redis不支持DEBUG功能,所以该命令执行无效。
- Lua脚本中执行Redis命令
与开源Redis一致,GeminiDB Redis的Lua环境中也提供了一个全局的“redis”表,用于提供各类和Redis Server交互的函数。
如下表为GeminiDB Redis目前支持和不支持的操作列表。
支持的操作 | 不支持的操作 |
---|---|
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() |
- Lua执行环境限制
开源Redis对Lua脚本的执行有一定的限制,比如限制脚本操作全局变量,限制随机函数的结果,限定能够使用的系统库和第三方库等。
GeminiDB Redis也继承了绝大多数的限制,但是针对如下情况,GeminiDB Redis与开源Redis存在差异:
- Write Dirty
开源Redis规定,如果某个脚本已经执行了写操作,那么就不能被SCRIPT KILL停止执行,必须使用SHUTDOWN NOSAVE来直接关闭Redis Server。
GeminiDB 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来允许用户决定这种场景下的行为模式。
对于GeminiDB Redis来说,由于没有主从的概念,数据在逻辑上只有一份,因此也就不存在该限制。
Lua脚本中禁用的命令列表
目前,在Lua脚本中禁用的GeminiDB Redis命令列表请参见命令兼容列表。