基於Redis實現的分佈式鎖,採用客戶端主動續期機制實現的Redis分佈式鎖,期望解決目前常見Redis分佈式鎖存在的本地線程未結束但遠程服務器鎖已過期的問題。
設計結構
該分佈式鎖,主要由本地線程管理器和遠程同步插件這兩大部件組成。
本地線程管理器:負責將本地請求同一個鎖的線程排隊,確保一把鎖只有一條線程在等待,其他線程暫時駐留,減少cpu資源的消耗。
遠程同步插件:負責與遠程服務器(Redis)同步鎖信息(申請、保活、釋放),同時它作爲一個插件,是可以根據需要選擇的(雖然目前版本暫時只有單節點Redis服務器這個版本的同步插件)。
對於本地線程同步器,在線程排隊的實現上,是藉助JDK的AQS抽象類實現的,因此它有AQS本身帶有的CAS樂觀鎖字段state
,當state>0
時,表示當前被某個線程佔有了state
次。爲了能夠線程安全地在本地線程管理器和遠程同步插件之間同步數據,本地線程管理器上增加了lockState
字段,同樣使用CAS的機制進行數據的同步(後面有可能會更換爲synchronized實現)。lockState
字段共存在5種狀態,爲了理解方便,使用用餐術語解釋這幾種狀態:
- 狀態值0,無需進食(即沒有業務線程需要從遠程服務器獲取鎖)
- 狀態值1,等待投食(即已有業務線程做好準備,等待同步器從遠程服務器獲取鎖,更新給它)
- 狀態值2,取消進食(在tryLock方法達到等待時間仍沒獲取到鎖的情況下,會取消等待鎖)
- 狀態值3,正在進食(即同步器已從遠程服務器獲取鎖,並已鎖更新給它,業務線程繼續執行,等待業務代碼執行完後釋放鎖)
- 狀態值4,收拾餐具(即業務線程調用了釋放鎖的方法,但同步器未將釋放鎖這個操作更新到遠程服務器)
使用方法
目前僅存在一個適配單Redis服務器(非集羣)的遠程同步插件SimpleRemoteSynchronizer,它使用SimpleRemoteConfigure來配置。使用方法如下:
SimpleRemoteConfigure configure = new SimpleRemoteConfigure();
configure.setKeyPrefix("lockinst");
configure.setServerHost("127.0.0.1");
DistributedLock distributedLock = new DistributedLock(configure);
try {
DistributedLock.Lock lock = distributedLock.lock("lockname");
// TODO 業務代碼
// ...
} finally {
lock.unlock();
}
pom.xml
<dependency>
<groupId>com.uetty.jedis</groupId>
<artifactId>online-lock</artifactId>
<version>1.0.1-Beta</version>
</dependency>
聯繫
歡迎大家幫忙測試、提交BUG、貢獻代碼
↘倉庫地址
↘個人郵箱