1.lua簡介
從 Redis 2.6.0 版本開始,通過內置的 Lua 解釋器,可以使用 EVAL 命令對 Lua 腳本進行求值。
Redis 使用單個 Lua 解釋器去運行所有腳本,并且, Redis 也保證腳本會以原子性(atomic)的方式執行:當某個腳本正在運行的時候,不會有其他腳本或 Redis 命令被執行。這和使用 MULTI / EXEC 包圍的事務很類似。在其他別的客戶端看來,腳本的效果(effect)要么是不可見的(not visible),要么就是已完成的(already completed)。
2.Lua腳本配置流程
在resource目錄下面新增一個后綴名為.lua結尾的文件
編寫腳本執行內容
調用redisTemplate.execute方法執行腳本
3.lua eval:http://doc.redisfans.com//eval.html 4.本地起兩個服務節點作為演示。演示代碼如下:
本文采用定時調度模擬線程去獲取鎖(鏈接:詳解Scheduled定時調度)
使用-Dserver.port=9527,-Dserver.port=9528開啟多個節點
local lock_key = KEYS[1]
local lock_value = KEYS[2]
local result = redis.call(‘SETNX’,lock_key,lock_value)
if result == 1
then
redis.call(‘SETEX’,lock_key,60,lock_value)
return result
else
return result
end
lua腳本redis客戶端執行命令如下:
redis-cli --eval xxxx.lua value value 。..。..。
ps:執行成功返回1,失敗返回0
local lock_key = KEYS[1]
local lock_value = KEYS[2]
local lock_time_out = KEYS[3]
local result = redis.call(‘SET’,lock_key,lock_value,‘EX’,lock_time_out,‘NX’)
return result
ps:執行成功返回OK,失敗返回nil
@Component
public class RedisLock {
@Autowired
private RedisTemplate redisTemplate;
private DefaultRedis《Boolean》 lock;
@Value(“${server.port}”)
private String port;
@Scheduled(cron = “0/5 * * * * *”)
public void lock {
String lock = “LockNxExJob”;
Boolean absent = false;
try {
// 獲取鎖
absent = luaExpress (lock, port);
if (!absent) {
System.out.println (String.format (“獲取鎖失敗!被%s拿走”, redisTemplate.opsForValue .get (lock)));
} else {
System.out.println (String.format (“獲取鎖成功!值為:%s”, redisTemplate.opsForValue .get (lock)));
}
} catch (Exception e) {
e.printStackTrace ;
} finally {
// 釋放鎖
if (absent) redisTemplate.delete (lock);
}
}
public Boolean luaExpress(String key, String value) {
lock = new DefaultRedis《》 ;
lock.setSource (new ResourceSource (new ClassPathResource (“lua\redis.lua”)));
lock.setResultType (Boolean.class);
List《Object》 list = new ArrayList《》 ;
list.add (key);
list.add (value);
Boolean result = (Boolean) redisTemplate.execute (lock, list);
return result;
}
}
ps:當節點9527成功獲取分布式鎖,在沒有執行釋放鎖之前,服務節點宕掉了,節點9528則會無法獲取到鎖,直到設置鎖的超時時間結束,才能獲得鎖。避免了單節點掛掉了,鎖一直未被釋放的尷尬場景。
5.總結
Redis 使用單個 Lua 解釋器去運行所有腳本,并且, Redis 也保證腳本會以原子性(atomic)的方式執行:當某個腳本正在運行的時候,不會有其他腳本或 Redis 命令被執行,保證了只要能setnx成功就能setex。解決了服務獲取鎖成功,但突然宕機,未能設置超時時間問題。
責任編輯 LK
-
代碼
+關注
關注
30文章
4788瀏覽量
68612 -
Lua
+關注
關注
0文章
81瀏覽量
10562 -
Redis
+關注
關注
0文章
375瀏覽量
10877
發布評論請先 登錄
相關推薦
評論