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命令列表請參見命令兼容列表。