在 Redis 上實現的分散式鎖

發表於2015-11-28

由於近排很忙,忙各種事情,還有工作上的專案,已經超過一個月沒寫部落格了,確實有點慚愧啊,沒能每天或者至少每週堅持寫一篇部落格。這一個月裡面接觸到很多新知識,同時也遇到很多技術上的難點,在這我將對每一個有用的技術點做一個小小的分析理解和總結。每天去學會總結,才會有進步。

本次對我在工作上的專案中用到的技術,在Redis上實現分散式鎖,進行一個分析和總結。

先了解下什麼是分散式鎖,在百科上是這麼定義的:

分散式鎖是控制分散式系統之間同步訪問共享資源的一種方式。在分散式系統中,常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源,那麼訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分散式鎖。

簡單的理解就是:分散式鎖是一個在很多環境中非常有用的原語,它是不同的系統或是同一個系統的不同主機之間互斥操作共享資源的有效方法。

背景:

在很多網際網路產品應用中,有些場景需要加鎖處理,比如:秒殺,全域性遞增ID,樓層生成等等。大部分是解決方案基於DB實現的,Redis為單程式單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶端對Redis的連線並不存在競爭關係。

我們的專案:

我們現在的專案中,任務佇列用到分散式鎖的情況比較多,在將業務邏輯中可以非同步處理的操作放入佇列,在其他執行緒中處理後出隊,此時佇列中使用了分散式鎖,保證入隊和出隊的一致性。關於redis佇列這塊的邏輯分析,我將在下一次對其進行總結,此處先略過。

接下來對redis實現的分散式鎖的邏輯程式碼進行詳細的分析和理解:

1、為避免特殊原因導致鎖無法釋放, 在加鎖成功後, 鎖會被賦予一個生存時間(通過 lock 方法的引數設定或者使用預設值), 超出生存時間鎖將被自動釋放.

2、鎖的生存時間預設比較短(秒級, 具體見 lock 方法), 因此若需要長時間加鎖, 可以通過 expire 方法延長鎖的生存時間為適當的時間. 比如在迴圈內呼叫 expire
3、系統級的鎖當程式無論因為任何原因出現crash,作業系統會自己回收鎖,所以不會出現資源丟失。
4、但分散式鎖不同。若一次性設定很長的時間,一旦由於各種原因程式 crash 或其他異常導致 unlock 未被呼叫,則該鎖在剩下的時間就變成了垃圾鎖,導致其他程式或程式重啟後無法進入加鎖區域。

此類很多程式碼都寫上了註釋,只要認真理解下,就很容易懂得如何在redis實現分散式鎖了。

另外,我在網上找到另一篇關於redis實現分散式鎖的文章:《使用 Redis 實現分散式鎖》。我感覺挺不錯的,推薦給大家。結合我所總結的和我推薦的文章做對比,基本上能理解清楚是如何在redis實現分散式鎖的了。

如果此博文中有哪裡講得讓人難以理解,歡迎留言交流,若有講解錯的地方歡迎指出。

相關文章