Redis在2.6版引入了對Lua的支持。
- 使用Lua可以非常明顯的提升Redis的效率。
Redis的一些命令
-
EVAL
執行Lua腳本 -
EVALSHA
執行Lua腳本的sha1 -
SCRIPT LOAD
加載Lua腳本到Redis Script -
SCRIPT FLUSH
清空Redis Script -
SCRIPT EXISTS
判斷是否存在Rdis Script中
EVAL
127.0.0.1:6379> eval "return 'Hello, world' " 0
"Hello, world"
在服務器中的Lua環境相當于定義了以下函數, 并且運行函數:
func f_9d4977f841f29202b7138237c28943c49565851b()
return 'Hello, world'
end
格式是固定的,為f_
+ Lua腳本的sha1值
EVALSHA
127.0.0.1:6379> evalsha 9d4977f841f29202b7138237c28943c49565851b 0
"Hello, world"
}
在服務器中的Lua環境中直接調用函數。
f_9d4977f841f29202b7138237c28943c49565851b()
這個地方需要特別注意的是,在沒有執行過eval
或script load
的lua腳本,直接調用會報錯,錯誤信息如下:(error) NOSCRIPT No matching script. Please use EVAL.
SCRIPT LOAD
127.0.0.1:6379> script load "return 'Hello, world' "
"9d4977f841f29202b7138237c28943c49565851b"
script load
會將Lua腳本加載到lua_script字典中。
SCRIPT EXISTS
127.0.0.1:6379> script exists 9d4977f841f29202b7138237c28943c49565851b
1) (integer) 1
檢查Lua腳本的sha1值是否存在lua_scripot字典中。
SCRIPT FLUSH
127.0.0.1:6379> script flush
OK
清空lua_script字典。
Redis 執行Lua腳本的過程
發送命令請求
EVAL "return redis.call('DBSIZE')" 0
Caller ------------------------------------------> Redis
為腳本 "return redis.call('DBSIZE')"
創建 Lua 函數
Redis ------------------------------------------> Lua
綁定超時處理鉤子
Redis ------------------------------------------> Lua
執行腳本函數
Redis ------------------------------------------> Lua
執行 redis.call('DBSIZE')
Fake Client <------------------------------------- Lua
偽客戶端向服務器發送
DBSIZE 命令請求
Fake Client -------------------------------------> Redis
服務器將 DBSIZE 的結果
(Redis 回復)返回給偽客戶端
Fake Client <------------------------------------- Redis
將命令回復轉換為 Lua 值
并返回給 Lua 環境
Fake Client -------------------------------------> Lua
返回函數執行結果(一個 Lua 值)
Redis <------------------------------------------ Lua
將 Lua 值轉換為 Redis 回復
并將該回復返回給客戶端
Caller <------------------------------------------ Redis
Redis使用Lua的注意事項
- 如果Lua腳本中包括全局變量時,會報錯。定義變量時不要落下
local
關鍵字。 - 一定要確保Lua腳本已經通過
load script
或eval
加載或執行腳本之后再調用evalsha
。 - 在一主多從的環境中,一定要注意使用
evalsha
時,從服務有可能會出現未成功加載lua腳本的情況。 - redis配置文件中一定要設置lua超時鉤子
lua-time-limit 5000
。