Redis的lua腳本
Redis在2.6推出了腳本功能,允許開發者使用 Lua 語言編寫腳本傳到 Redis 中執行。
1、使用lua腳本的優點:
(1)減少網絡開銷:多次網絡請求的操作,可以用一個請求完成,原先多次請求的邏輯放在redis服務器上完成。使用腳本,減少了網絡往返時延。
(2)原子操作:Redis會將整個腳本作為一個整體執行,中間不會被其他命令插入。管道不是原子的,不過redis的批量操作命令(類似mset)是原子的。
(3)替代redis的事務功能:redis自帶的事務功能很雞肋,報錯不支持回滾,而redis的lua腳本幾乎實現了常規的事務功能,支持報錯回滾操作;官方推薦如果要使用redis的事務功能可以用redis lua替代。
2、可以使用 EVAL命令對Lua腳本進行求值。EVAL命令的格式如下:
EVAL script numkeys key [key ...] arg [arg ...]
說明:
script:是一段Lua腳本程序 ,它會被運行在Redis服務器上下文中,這段腳本不必(也不應該)定義為一個Lua函數。
numkeys:用於指定鍵名參數的個數。
key [key ...]: 從EVAL的第三個參數開始算起,表示在腳本中所用到的那些Redis鍵(key),這些鍵名參數可以在 Lua中通過全局變量KEYS數組,用1為基址的形式訪問( KEYS[1] , KEYS[2] ,以此類推)。
arg [arg ...]:在命令的最后,那些不是鍵名參數的附加參數 arg [arg ...] ,可以在Lua中通過全局變量ARGV數組訪問,訪問的形式和KEYS變量類似( ARGV[1] 、 ARGV[2])
例如:
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
在 Lua 腳本中,可以使用 redis.call() 函數來執行Redis命令。
Jedis調用示例:
jedis.set("product_stock_10000", "15"); //初始化商品10000的庫存
String script = " local count = redis.call('get', KEYS[1]) " +
" local a = tonumber(count) " +
" local b = tonumber(ARGV[1]) " +
" if a >= b then " +
" redis.call('set', KEYS[1], count‐b) " +
" return 1 " +
" end " +
" return 0 "; Object obj = jedis.eval(script, Arrays.asList("product_stock_10000"), Arrays.asList("10")); System.out.println(obj);
注意:不要在Lua腳本中出現死循環和耗時的運算,否則redis會阻塞,將不接受其他的命令, 所以使用時要注意不能出現死循環、耗時的運算。redis是單進程、單線程執行腳本。管道不會阻塞redis。
lua 腳本執行報錯會進行回滾操作。