Lua脚本规范 本节主要介绍Lua脚本规范。 Lua是一种脚本语言,目的是为了嵌入应用程序中,为应用程序提供灵活的扩展和定制功能。GeminiDB 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 GeminiDB Redis是多线程执行的环境,允许同时执行多个Lua脚本,执行SCRIPT KILL,会终止所有正在运行的Lua脚本。 为了方便使用,GeminiDB Redis扩展了SCRIPT KILL命令,用户可以通过‘SCRIPT KILL SHA1’来终止指定哈希值的脚本。若同一时间存在多个节点在执行哈希值相同的脚本,那么这些脚本都会被终止。 另外,由于用户无法设置Lua超时时间(config set luatimelimit),因此在任意时刻执行SCRIPT KILL都能直接终止脚本,而不是等待脚本超时后才终止。 SCRIPT DEBUG 目前GeminiDB Redis不支持DEBUG功能,所以该命令执行无效。 3. Lua脚本中执行Redis命令 与开源Redis一致,GeminiDB Redis的Lua环境中也提供了一个全局的“redis”表,用于提供各类和Redis Server交互的函数。 如下表为GeminiDB Redis目前支持和不支持的操作列表。 支持的操作 不支持的操作 redis.call() redis.pcall() redis.sha1hex() redis.errorreply() redis.statusreply() redis.log() redis.LOGDEBUG redis.LOGVERBOSE redis.LOGNOTICE redis.LOGWARNING redis.replicatecommands() redis.setrepl() redis.REPLNONE redis.REPLAOF redis.REPLSLAVE redis.REPLREPLICA redis.REPLALL redis.breakpoint() redis.debug() 4. 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引入了replicatecommands来允许用户决定这种场景下的行为模式。 对于GeminiDB Redis来说,由于没有主从的概念,数据在逻辑上只有一份,因此也就不存在该限制。