4.8 利用Java代碼調用Lua腳本改造分布式鎖
lua腳本本身并不需要大家花費太多時間去研究,只需要知道如何調用,大致是什么意思即可,所以在筆記中并不會詳細的去解釋這些lua表達式的含義。
我們的RedisTemplate中,可以利用execute方法去執(zhí)行l(wèi)ua腳本,參數對應關系就如下圖股
Java代碼
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
static {
UNLOCK_SCRIPT = new DefaultRedisScript<>();
UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
UNLOCK_SCRIPT.setResultType(Long.class);
}
public void unlock() {
// 調用lua腳本
stringRedisTemplate.execute(
UNLOCK_SCRIPT,
Collections.singletonList(KEY_PREFIX + name),
ID_PREFIX + Thread.currentThread().getId());
}
經過以上代碼改造后,我們就能夠實現(xiàn) 拿鎖比鎖刪鎖的原子性動作了~
小總結:
基于Redis的分布式鎖實現(xiàn)思路:
- 利用set nx ex獲取鎖,并設置過期時間,保存線程標示
- 釋放鎖時先判斷線程標示是否與自己一致,一致則刪除鎖
- 特性:
- 利用set nx滿足互斥性
- 利用set ex保證故障時鎖依然能釋放,避免死鎖,提高安全性
- 利用Redis集群保證高可用和高并發(fā)特性
- 特性:
筆者總結:我們一路走來,利用添加過期時間,防止死鎖問題的發(fā)生,但是有了過期時間之后,可能出現(xiàn)誤刪別人鎖的問題,這個問題我們開始是利用刪之前 通過拿鎖,比鎖,刪鎖這個邏輯來解決的,也就是刪之前判斷一下當前這把鎖是否是屬于自己的,但是現(xiàn)在還有原子性問題,也就是我們沒法保證拿鎖比鎖刪鎖是一個原子性的動作,最后通過lua表達式來解決這個問題
但是目前還剩下一個問題鎖不住,什么是鎖不住呢,你想一想,如果當過期時間到了之后,我們可以給他續(xù)期一下,比如續(xù)個30s,就好像是網吧上網, 網費到了之后,然后說,來,網管,再給我來10塊的,是不是后邊的問題都不會發(fā)生了,那么續(xù)期問題怎么解決呢,可以依賴于我們接下來要學習redission啦
測試邏輯:文章來源:http://www.zghlxwxcb.cn/news/detail-846273.html
第一個線程進來,得到了鎖,手動刪除鎖,模擬鎖超時了,其他線程會執(zhí)行l(wèi)ua來搶鎖,當第一天線程利用lua刪除鎖時,lua能保證他不能刪除他的鎖,第二個線程刪除鎖時,利用lua同樣可以保證不會刪除別人的鎖,同時還能保證原子性。文章來源地址http://www.zghlxwxcb.cn/news/detail-846273.html
到了這里,關于利用Java代碼調用Lua腳本改造分布式鎖的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!