在互聯網分佈式服務部署中,通常會遇到多個進程操作同一個資源的情況,例如秒殺等,此文章主要介紹使用Redis實現分佈式鎖。
Redis爲單進程單線程模式,採用隊列模式將併發訪問變爲串行訪問。通常使用setnx(即set not exiest)來實現鎖,以下通過循序漸進的方式引入最終實現。
方案一
1. C1通過setnx獲取鎖,處理業務,C1通過del釋放鎖
問題:如果處理業務期間C1崩潰,導致死鎖
方案二
1. C1通過setnx獲取鎖,鎖裏面設置爲時間戳,全局業務中有配置超時時間EXPIRE,處理業務,C1由於其他原因崩潰
2. C2,C3通過setnx獲取鎖失敗
3. 使用get獲取T1,T2,且CURTIME>T1(T2)+EXPIRE,超時(若未超時,則sleep,然後重新進入第2步)
4. C2,C3分別使用del刪除鎖
5. C2,C3分別使用setnx獲取鎖(若未獲取到,則sleep,然後重新進入第2步)
問題:C2,C3串行執行情況下,C2獲取的鎖會被C3刪除,從而導致競態
方案三
1. C1通過setnx獲取鎖,鎖裏面設置爲時間戳,全局業務中有配置超時時間EXPIRE,處理業務,C1由於其他原因崩潰
2. C2,C3通過setnx獲取鎖失敗
3. 使用get獲取T1,T2(爲nil也進入判斷),且CURTIME>T1(T2)+EXPIRE,超時(若未超時,則sleep,然後重新進入第2步)
4. C2,C3分別使用getset,獲取到T11,T22(爲nil也進入判斷),此時若T11=T1則C2獲取鎖(T22=T2則C3獲取鎖,二者只會有1個成立),執行業務。(若未獲取到的,則sleep,然後重新進入第2步)