轉載至笑松小站http://blog.seoui.com/2018/01/27/redis-lua/ redis從2.6版本開始內置支持Lua解釋器,解釋器提供了3個函數來處理redis的命令redis.call() redis.pcall()和 redis.log,同時redis 也保證腳本會以原 ...
轉載至笑松小站http://blog.seoui.com/2018/01/27/redis-lua/
redis
從2.6版本開始內置支持Lua
解釋器,解釋器提供了3個函數來處理redis
的命令redis.call()
redis.pcall()
和 redis.log
,同時redis
也保證腳本會以原子性的方式執行。這是一個很重要的因素。
本文涉及到的命令有 EVAL
EVALSHA
SCRIPT LOAD
SCRIPT FLUSH
SCRIPT EXISTS
SCRIPT KILL
redis.call(), redis.pcall() 函數的區別就是處理錯誤異常的情況不同,其他的功能是一樣的 具體使用哪個看需求而論
redis.call()
執行命令的過程中發生錯誤時,腳本會停止執行,並返回一個腳本錯誤redis.pcall()
執行命令的過程中發生錯誤時,腳本會繼續執行,但是會記錄錯誤信息 返回一個帶 err 域的 Lua 表(table)redis.log(loglevel, message)
觸發redis
記錄日誌 日誌級別有 redis.LOG_DEBUG redis.LOG_VERBOSE redis.LOG_NOTICE redis.LOG_WARNING
EVAL
EVAL
命令對 Lua
腳本進行執行求值。
語法:EVAL script numkeys key [key …] arg [arg …]
script
lua腳本內容 註意的是腳本不應該是Lua
函數。numkeys
表示指定鍵名參數的個數。key [key ...]
表示腳本對應的key
值列表 在腳本中可以使用KEYS[1]
KEYS[2]
KEYS[3]
KEYS[n]
n從1開始 。arg [arg ...]
命名行中傳遞的參數列表 在腳本中可以使用ARGV[1]
ARGV[2]
ARGV[3]
ARGV[n]
n從1開始 。
一個示例勝過千言萬語的解釋
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 id name 3 mytest |
執行上面腳本返回
1) "id" 2) "name" 3) "2" 4) "mytest" |
EVALSHA
此命令和EVAL
的區別是EVAL
每次都需要傳入腳本的主體內容,對網路帶寬不是很友好。而EVALSHA
命令正好可以解決這個問題。
語法: EVALSHA sha1 numkeys key [key …] arg [arg …]
sha1
緩存中的sha
值 這個值可以利用SCRIPT LOAD
生成numkeys
表示指定鍵名參數的個數。key [key ...]
表示腳本對應的key
值列表 在腳本中可以使用KEYS[1]
KEYS[2]
KEYS[3]
KEYS[n]
n從1開始 。arg [arg ...]
命名行中傳遞的參數列表 在腳本中可以使用ARGV[1]
ARGV[2]
ARGV[3]
ARGV[n]
n從1開始 。
> SCRIPT LOAD "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" "a42059b356c875f0717db19a51f6aaca9ae659ea" > EVALSHA a42059b356c875f0717db19a51f6aaca9ae659ea 2 id name 2 mytest 1) "id" 2) "name" 3) "2" 4) "mytest" > |
1、首先利用SCRIPT LOAD
把腳本的主體緩存在redis
中,會返回一個sha的key
2、EVALSHA
執行命令 把sha帶上 其他的和eval沒有區別。
腳本緩存
redis
保證了所有運行過的腳本都能緩存起來 前面也提到過使用SCRIPT LOAD
也能將腳本緩存並返回sha值,那麼也能使用SCRIPT FLUSH
清空腳本緩存
SCRIPT LOAD
載入腳本到緩存中SCRIPT FLUSH
清除所有 Lua 腳本緩存。SCRIPT EXISTS
判斷sha值是否已經緩存好了,返回值為 0 和 1 ,後者表示存在於緩存中,在程式開發中非常有用 比如redis
出現了什麼異常情況後,腳本緩存被清空了,或者被人為執行了SCRIPT FLUSH
命令,這個時候就可以優先嘗試一下SCRIPT EXISTS
命令如果返回0表示不存在 就需要先執行SCRIPT LOAD
先把腳本載入到緩存中之後再執行
SCRIPT KILL
殺死當前正在運行的 Lua
腳本,當且僅當這個腳本沒有執行過任何寫操作時,這個命令才生效
。
SCRIPT KILL
執行成功返回OK,其他情況返回錯誤信息
業務場景案例
- spring-cloud-gateway springc cloud 網關限流
- 需要原子操作的零散邏輯
- 分散式限流
- ….