首先明確分散式鎖應該具備什麼特性:獲取鎖的業務無論正常與否,都必須能釋放鎖,這樣才能避免死鎖;鎖應該具有高可用性。
我們來看看redis是怎麼來實現鎖的的。
redis主要是透過setnx、get、getset、del命令來完成加鎖,搶鎖和釋放鎖的操作的,這裡我用兩個客戶端來模擬下加鎖的過程。下面有實際操作的截圖。
1、客戶端1使用setnx獲取到鎖,並設定鎖的當前時間。設定超時時間就是為了業務掛了,鎖不能釋放成為死鎖。
執行命令
setnx lock 0
為了方便舉例,我們假定鎖的當前時間是從0秒開始的,超時時間為3秒。如果結果返回為1,表明加鎖成功,可以執行業務邏輯了。
2、當第一秒鐘客戶端2使用setnx獲取鎖,執行命令
setnx lock 1
返回值為0,則加鎖失敗。
3、客戶端2接收到加鎖時間的迴應後,會去檢視鎖是否超時。執行命令
get lock
返回值為加鎖的時間,假設現在時間已經到第4秒了,客戶端會使用返回的時間0加上超時時間3小於當前時間4,鎖已經超時了。
4、客戶端2使用getset命令去獲取鎖。
getset lock 4
這時候返回的是前一次加鎖的時間,如果這個時間是0,證明加鎖成功,因為和前一次get的值相同。如果不同,說明鎖已經被別人搶佔了,加鎖失敗,繼續重複步驟3和4。
5、業務執行完成後,判斷下鎖是否超時,沒有超時,不用管了。如果沒有超時,呼叫del命令釋放鎖即可。
redis存在的問題
1、redis如果是單機的話是有單點問題的,不滿足高可用性。redis叢集因為是ap模型,是不能保證一致性的,官方提供了redlock演算法來解決這個問題,但是至少需要3個master-slave節點才能完成,成本也較大。redlock相當於是來實現一致性協議的。
2、鎖的超時時間設定問題,太長太短都不合適,太長了如果服務掛掉了會一直阻塞業務,太短了有可能業務還沒執行完成就釋放了。當然可以用官方提供redisson解決。
首先明確分散式鎖應該具備什麼特性:獲取鎖的業務無論正常與否,都必須能釋放鎖,這樣才能避免死鎖;鎖應該具有高可用性。
我們來看看redis是怎麼來實現鎖的的。
redis主要是透過setnx、get、getset、del命令來完成加鎖,搶鎖和釋放鎖的操作的,這裡我用兩個客戶端來模擬下加鎖的過程。下面有實際操作的截圖。
1、客戶端1使用setnx獲取到鎖,並設定鎖的當前時間。設定超時時間就是為了業務掛了,鎖不能釋放成為死鎖。
執行命令
setnx lock 0
為了方便舉例,我們假定鎖的當前時間是從0秒開始的,超時時間為3秒。如果結果返回為1,表明加鎖成功,可以執行業務邏輯了。
2、當第一秒鐘客戶端2使用setnx獲取鎖,執行命令
setnx lock 1
返回值為0,則加鎖失敗。
3、客戶端2接收到加鎖時間的迴應後,會去檢視鎖是否超時。執行命令
get lock
返回值為加鎖的時間,假設現在時間已經到第4秒了,客戶端會使用返回的時間0加上超時時間3小於當前時間4,鎖已經超時了。
4、客戶端2使用getset命令去獲取鎖。
getset lock 4
這時候返回的是前一次加鎖的時間,如果這個時間是0,證明加鎖成功,因為和前一次get的值相同。如果不同,說明鎖已經被別人搶佔了,加鎖失敗,繼續重複步驟3和4。
5、業務執行完成後,判斷下鎖是否超時,沒有超時,不用管了。如果沒有超時,呼叫del命令釋放鎖即可。
redis存在的問題
1、redis如果是單機的話是有單點問題的,不滿足高可用性。redis叢集因為是ap模型,是不能保證一致性的,官方提供了redlock演算法來解決這個問題,但是至少需要3個master-slave節點才能完成,成本也較大。redlock相當於是來實現一致性協議的。
2、鎖的超時時間設定問題,太長太短都不合適,太長了如果服務掛掉了會一直阻塞業務,太短了有可能業務還沒執行完成就釋放了。當然可以用官方提供redisson解決。