1. 為何要使用分布式鎖
在分布式系統(tǒng)中,多個服務(wù)實例可能同時訪問共享資源,傳統(tǒng)的本地鎖失效。分布式鎖應(yīng)運而生,解決以下關(guān)鍵問題:
- 并發(fā)資源訪問控制
- 防止數(shù)據(jù)不一致
- 避免重復(fù)操作
- 保證業(yè)務(wù)原子性
典型場景:
- 訂單生成
- 庫存扣減
- 秒殺系統(tǒng)
- 分布式任務(wù)調(diào)度
2. 分布式鎖的幾種實現(xiàn)方式
2.1 數(shù)據(jù)庫實現(xiàn)
-- 悲觀鎖
SELECT * FROM table WHERE id = ? FOR UPDATE
優(yōu)點:簡單直接
缺點:性能低,數(shù)據(jù)庫壓力大
2.2 ZooKeeper實現(xiàn)
// 創(chuàng)建臨時順序節(jié)點
create -e -s /lock path
優(yōu)點:可靠性高
缺點:依賴ZooKeeper集群
2.3 Redis實現(xiàn)
--加鎖
SET key value NX PX 30000
優(yōu)點:性能高
缺點:需要自己實現(xiàn)續(xù)期機制
3. 為什么總選擇Redis?
- 性能優(yōu)勢
- 內(nèi)存操作,毫秒級響應(yīng)
- 原子操作命令
- 支持集群和高可用
- 實現(xiàn)簡單
4. Redisson的優(yōu)越性
既然是redis,那么開箱即用,便是大家所需,redission應(yīng)運而生
- 功能全面
- 自動續(xù)期
- 可重入鎖
- 公平鎖
代碼示例
RLock lock = redissonClient.getLock("myLock");
lock.lock();
try {
// 業(yè)務(wù)邏輯
} finally {
lock.unlock();
}
5. Redisson看門狗失效及解決
redission雖然有看門狗續(xù)命機制,但也不能做到萬無一失
5.1 失效場景
有垃圾收集器( GC ),有時運行期間會暫停所有正在運行的線程。這些GC暫停甚至有時會持續(xù)數(shù)分鐘 !即使像HotSpot JVM CMS所謂的“并發(fā)”垃圾收集器也不能完全與應(yīng)用代碼并行運行,需要時時地停止活動的線程。通過改變分配模式或調(diào)整GC某些參數(shù)可 減少暫停,但是我們還是要防范最差情況以提供可靠的保證。
當(dāng)操作系統(tǒng)執(zhí)行線程上下文切換時,或者虛擬機管理程序切換到 個虛機時
正在運行的線程可能會在代碼的任意位置被暫停。在虛擬機環(huán)境中,這種被其
虛擬機中斷的 PU時間稱為竊取時間 。如果機器負載很高( 等待運行的錢程很
長),被暫停的線程可能需要 段時間之后才能再次運行。如果操作系統(tǒng)配置了基于磁盤的內(nèi)存交換分區(qū),內(nèi)存訪問可能觸發(fā)缺頁中斷,進
而需要從磁盤中加載內(nèi)存頁。 I/O 進行時(通常比較慢)線程為暫停。如果內(nèi)存
使用壓力很大,還可能迫使更多的頁面換出到磁盤 極端的情況下,操作系統(tǒng)可
會花費大量時間在頁面換入換出上,而實際工作完成很少(所謂的顛簸’)。為
了避免 問題,通常在服務(wù)器上禁用分頁,寧愿殺死一些進程來釋放內(nèi) 而不
是反復(fù)抖動。
總之,當(dāng)節(jié)點1拿到鎖在執(zhí)行時,如果看門狗未來的及續(xù)命,被暫停了,而redis鎖過期了,節(jié)點2就有可能拿到鎖,然后節(jié)點1復(fù)活繼續(xù)執(zhí)行,就會造成并發(fā)問題
5.2解決方案
5.2.1 顯式設(shè)置超時
// 增加鎖的超時時間
RLock lock = redissonClient.getLock("your_lock");
lock.lock(60, TimeUnit.SECONDS); // 顯式設(shè)置較長超時
5.2.2 業(yè)務(wù)冪等設(shè)計
- 唯一請求ID
- 狀態(tài)機
- 補償機制
5.2.3 JVM參數(shù)調(diào)優(yōu)
調(diào)整JVM GC策略
優(yōu)化Full GC頻率和時間
使用G1或ZGC替代
增加鎖的容錯機制
# 調(diào)整內(nèi)存大小
-Xms4g -Xmx4g # 初始和最大堆內(nèi)存一致
-XX:MaxMetaspaceSize=256m # 限制元空間大小
# 垃圾回收器選擇
-XX:+UseG1GC # 推薦G1收集器
-XX:MaxGCPauseMillis=200 # 控制最大GC停頓時間
# 減少Full GC頻率
-XX:+DisableExplicitGC # 禁止顯式調(diào)用System.gc()
結(jié)語
分布式鎖是分布式系統(tǒng)中的利器,選擇合適的方案和框架至關(guān)重要。Redisson提供了強大且易用的分布式鎖解決方案,但仍需謹慎設(shè)計和使用。