回覆列表
  • 1 # O謎嘎

    實現分散式鎖常採用兩種方式,一種是基於redis,一種基於zookeeper

    基於Redis 的分散式鎖

    基於redis的分散式鎖實現原理是使用redis的set nx ,就是當key不存在時才能設定成功,否則返回false,多例項併發去獲取鎖時由於redis的原子性以及set nx的特性,有一個例項能設定成功後,其他例項則不能獲取鎖,這時設定成功的例項拿到了這把鎖,其他的例項自然沒能拿到鎖。

    存在問題:redis很容易單點故障,如果使用官方的redlock也存在很大大爭議,而且實現複雜,所以一般基於zookeeper實現。

    基於zookeeper的實現

    在zookeeper的某一節點下多個例項建立同一個臨時節點,由於zookeeper中同一個節點是唯一的,也就是隻有一個例項能建立成功,建立成功則獲取到鎖,否則不該持有鎖。zookeeper是基於paxios演算法的,能保證高可用,強一致性,效能比redis實現稍弱。

    如何避免死鎖

    redis在設定鎖時提供超時時間,如果客戶端宕機,在超時時間過後鎖自動釋放。

  • 2 # 會點程式碼的大叔

    我不寫具體的程式碼,就花幾分鐘介紹一下什麼是分散式鎖,以及實現方案。

    為什麼需要分散式鎖

    在單個應用中,如果多個執行緒需要同時對一個數據進行修改,那麼Java可以使用併發處理相關的API來保證,同一個時間,這個資料只能被一個執行緒修改,例如synchronized。

    但是在分散式的環境當中,經常會有多個應用要同時修改同一個資料,如果不做互斥的話,很容易造成“未知的異常”。

    比如商城,商品剩餘量只有一件,如果碰巧兩個應用同時要扣除商品數量,如果不做互斥的話,那麼會出現明明商品數量不足,但是依然下單成功的情況。

    分散式鎖應該具備哪些條件同一時間只能被一個機器的一個執行緒執行;高效能的獲得鎖和釋放鎖;具有失效機制,防止死鎖;又分阻塞鎖和非阻塞鎖,前者沒有獲得鎖就等著,後者沒有獲得鎖會直接返回失敗。實現方式

    基於ZooKeeper:ZooKeeper是一個為分散式應用提供一致性服務的開源元件。大概的思路就是利用臨時節點與 watch 機制。每個鎖佔用一個普通節點/lock,當需要獲取鎖時在/lock目錄下建立一個臨時節點,建立成功則表示獲取鎖成功,失敗則 watch/lock 節點,有刪除操作後再去爭鎖。

    基於Redis:基於 redis 的 setnx()、get()、getset()方法做分散式鎖。

  • 3 # 淺析架構

    一.可以使用redis,zookeeper,etcd是實現分散式鎖

    二.redis主要是透過setnx、get、getset、del命令來完成加鎖,搶鎖和釋放鎖的操作的。

    1.setnx實現加鎖,返回1加鎖成功

    2.get檢視鎖是否超時

    3.超時了使用getset搶鎖

    4.del實現釋放鎖

    redis存在的問題

    1、redis如果是單機的話是有單點問題的。

    redis叢集因為是ap模型,是不能保證一致性的,官方提供了redlock演算法來解決這個問題,但是至少需要3個master-slave節點才能完成,成本也較大。redlock相當於是來實現一致性協議的。

    2、鎖的超時時間設定問題,太長太短都不合適,太長了如果服務掛掉了會一直阻塞業務,太短了有可能業務還沒執行完成就釋放了。當然可以用官方提供redisson解決。

    三.zookeeper是基於順序臨時節點和watch機制實現分散式鎖的

    1.順序節點可以保證最小的節點獲取鎖

    2.臨時節點可以保證業務掛了,可以釋放鎖

    3.監聽機制可以保證鎖釋放後及時得到通知,再次獲取鎖

    zk採用zab協議保證一致性,並且不用設定超時時間了,如果服務加鎖掛掉了,臨時節點也會自動刪除。 也可用使用Apache開源的 curator框架, 自帶了分散式鎖解決方案,原理和上述差不多。 zk加鎖釋放鎖都是透過動態建立節點、銷燬節點來實現的,效能消耗較大。

    四.etcd呼叫可以透過restful API的方式進行,這些需要透過prevExist實現分散式鎖,如果prevExist為true, 則這是一個更新請求,如果prevExist的值是false,則是一個建立請求。

    1.server1獲取鎖,設定超時時間是3秒 http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=false

    2.為了防止業務還沒有執行完,鎖釋放,所以每隔1秒需求重新設定下值。這個就是鎖續租約。 http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=true

    3.server2這時候去獲取鎖,則會失敗 http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=false

    4.server2可以監聽lock的變化。當lock目錄有變化的時候就會接到通知,然後重複步驟3。 這裡要注意watch事件不能太多。 http://127.0.0.1:2379/v2/keys/lock?wait=true

    上面這個是etcd2的實現,etcd3本身已經支援分散式鎖了,key增加Revision了,客戶端可以判定自己key對應的Revision是不是最小來獲取鎖,機制和zk獲取最小值類似。

    上面就是redis、zk、etcd怎麼實現分散式鎖的過程了。 每種方案都有公司在使用,也比較成熟了。

    只要能保持讀取和修改狀態是原子性操作都能當鎖使用,但是分散式鎖需要明確的幾個條件:

    獲取鎖的業務無論正常還是異常,都需要保證可以釋放,否則會出現死鎖的情況,還有就是鎖釋放後需要及時讓等待鎖的一方知道,方便再次獲取鎖。

  • 中秋節和大豐收的關聯?
  • 馬卡報:“已經有了安蘇.法蒂,巴薩為什麼還要買內馬爾?”你認可這一觀點嗎?