什麼是分佈式鎖
- 分佈式鎖: 進行邏輯處理時經常會遇到併發問題。可以藉助redis來實現分佈式鎖,簡單來說就是限制兩個操作不同時進行,每次執行某個操作的時候用setnx()加鎖,當沒被鎖再執行下一個操作.限制程序的併發執行!
- 一般步驟: 使用 setnx(set if not exists) 指令,只允許被一個客戶端佔坑。先來先佔,用完了,再調用 del 指令釋放茅坑。
- setnx lock:XXX true
分佈式鎖問題
-
鎖的釋放問題: 如果執行到一半出現問題,沒有執行del釋放鎖,那麼鎖就得不到釋放
可以給鎖加個expire過期時間
-
鎖的超時問題: 當設置過期時間比較短的時候,可能程序還未執行完畢,鎖已經超時過期了.第二個線程重新持有了這把鎖, 但是緊接着第一個線程執行完了業務邏輯,就把鎖給釋放了,第三個線程就會在第二個線程邏 輯執行完之間拿到了鎖。(超時後使用del 導致誤刪其他線程的鎖)
- 分佈式鎖不要用於長時間的任務
- 給value設置一個隨機數,釋放的時候匹配隨機數是否一致再刪除
- 編寫守護進程,當一個鎖快要過期的時候,任務還未結束,可以給鎖續一波命(過期時間),任務結束關閉該守護進程
lua腳本實現匹配和刪除的一個原子操作
# delifequals
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
<?php
// php中使用redis執行lua腳本
$lua = <<<SCRIPT
lua代碼
SCRIPT;
$s = $redis->eval($lua,'參數');
- 請求加鎖失敗的處理:
- 拋出異常,稍後重試
- 將請求添加到延時隊列
- sleep幾秒鐘
分佈式鎖應用場景
- 訂單等併發請求
- 任務隊列