在互聯(lián)網(wǎng)分布式服務(wù)部署中,通常會(huì)遇到多個(gè)進(jìn)程操作同一個(gè)資源的情況,例如秒殺等,此文章主要介紹使用Redis實(shí)現(xiàn)分布式鎖。
Redis為單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn)。通常使用setnx(即set not exiest)來(lái)實(shí)現(xiàn)鎖,以下通過(guò)循序漸進(jìn)的方式引入最終實(shí)現(xiàn)。
方案一
1. C1通過(guò)setnx獲取鎖,處理業(yè)務(wù),C1通過(guò)del釋放鎖
問(wèn)題:如果處理業(yè)務(wù)期間C1崩潰,導(dǎo)致死鎖
方案二
1. C1通過(guò)setnx獲取鎖,鎖里面設(shè)置為時(shí)間戳,全局業(yè)務(wù)中有配置超時(shí)時(shí)間EXPIRE,處理業(yè)務(wù),C1由于其他原因崩潰
2. C2,C3通過(guò)setnx獲取鎖失敗
3. 使用get獲取T1,T2,且CURTIME>T1(T2)+EXPIRE,超時(shí)(若未超時(shí),則sleep,然后重新進(jìn)入第2步)
4. C2,C3分別使用del刪除鎖
5. C2,C3分別使用setnx獲取鎖(若未獲取到,則sleep,然后重新進(jìn)入第2步)
問(wèn)題:C2,C3串行執(zhí)行情況下,C2獲取的鎖會(huì)被C3刪除,從而導(dǎo)致競(jìng)態(tài)
方案三
1. C1通過(guò)setnx獲取鎖,鎖里面設(shè)置為時(shí)間戳,全局業(yè)務(wù)中有配置超時(shí)時(shí)間EXPIRE,處理業(yè)務(wù),C1由于其他原因崩潰
2. C2,C3通過(guò)setnx獲取鎖失敗
3. 使用get獲取T1,T2(為nil也進(jìn)入判斷),且CURTIME>T1(T2)+EXPIRE,超時(shí)(若未超時(shí),則sleep,然后重新進(jìn)入第2步)
4. C2,C3分別使用getset,獲取到T11,T22(為nil也進(jìn)入判斷),此時(shí)若T11=T1則C2獲取鎖(T22=T2則C3獲取鎖,二者只會(huì)有1個(gè)成立),執(zhí)行業(yè)務(wù)。(若未獲取到的,則sleep,然后重新進(jìn)入第2步)