分布式鎖的實現原理

2021-10-17 08:56:51 字數 3006 閱讀 4939

在介紹分布式鎖之前,我們先來簡單介紹下執行緒鎖、程序鎖。

執行緒鎖

執行緒鎖,主要用來解決的問題是:保護臨界區域。

使用方式:lock(mutex)、unlock(mutex)。

程序鎖

為了控制同一作業系統中多個程序訪問乙個共享資源。

nginx中的accept鎖,就是一種程序鎖,它採用的實現方式是:共享記憶體+訊號量。

分布式鎖的常見實現方案有:

1)資料庫 redis,mysql

2)zookeeper

高效性比較:zookeeper > redis > mysql

1)互斥性

2)可重入性:乙個程序允許遞迴獲取鎖(需要遞迴釋放)

3)分布式鎖需要解決鎖超時(程序crash掉,需要考慮釋放分布式鎖)

4)高效、高可用(redis、zookeeper)。

5)公平鎖(按獲取鎖順序執行)和非公平鎖(隨機執行)

圖1

高可用,指的是資料中心crash掉後 ,程序依然可以獲取到鎖,並能夠正確釋放鎖。

redis主從複製:主redis收到寫操作,通知從redis方式實現資料同步,實現的是最終一致性(可能一秒rdb或者乙個操作aof)。

zookeeper:使用zab協議,實現強一致性

分布式中,主要考慮cap,c一致性,a可用性,p分割槽容錯性(三者佔二)。

1、redis執行原理

redis用作快取資料庫,也是資料結構資料庫,kv資料庫(hash)。

圖2

熱點資料(常用)存放在redis中。

操作redis,實際是操作redis中的資料結構,rpc遠端呼叫。

資料請求方式:請求回應+監聽發布。

按請求順序來執行命令,同樣返回按照執行順序。

比如:請求:set hello world

回應:+ok

2、redis實現分布式鎖

1)獲取鎖

2)執行邏輯

3)釋放鎖

設定鎖:setnx()只有在key不存在的時候,才能設定成功。成功返回(+ok),失敗返回(nil)。

釋放鎖:del key

結合圖1,引出幾個問題。

問題1程序a、b、c、d同時競爭鎖,若產生了死鎖,如何解決?

問題2來自問題1的設定超時解決方案:程序a超時後,還需要釋放鎖嗎?怎麼釋放?

問題3同樣來自問題1的設定超時解決方案:當a設定鎖超時之後,b可以獲取到鎖,如果b還沒執行完邏輯而a執行完後,a釋放了鎖,這時c也可以獲取鎖。

我們可以通過增加是哪個程序標識,表明是哪個進行在使用鎖。這樣a就不能隨意釋放鎖。

問題4來自問題3的設定超時解決方案:如何對乙個程序進行唯一標識?

1)方案1:使用 「pid」 作為程序唯一標識。缺陷:pid是乙個遞增id,最大值有上限,約是32970,當id值增加到最大值的時候,系統就會重新從1開始分配pid,沒法區分,因此僅使用pid並不合適。

2)方案2:使用 「ip:port:pid」 作為程序唯一標識:會產生一種bug–可能通過批處理執行過很多命令,1270pid輪詢重啟後又變成1270,這個時候沒法區分該程序是否有重啟。

3)方案3:使用 「ip:port:starttime:pid」 作為程序唯一標識,starttime是以ms單位來儲存。

zookeeper主要處理協調管理功能:統一命名、管理集群、配置中心(配置更新)、分布式鎖。

圖3

整合zookeeper之後,一般都是配置乙個web後台。可以在web後台對zookeeper進行配置更新。zookeeper就可以呼叫批處理程式,比如重啟等。

zookeeper通過資料模型+監聽機制,來驅動所有的功能。

1、資料模型

類似檔案系統儲存方式

/root

/usr/local

特徵:圖4

2、監聽機制

可監聽節點的變化(建立,刪除,值的變化,子節點的變化(建立或刪除))。

1)獲取鎖:建立同名節點,只有乙個能建立成功。

2)釋放鎖:delete節點,斷開連線自動刪除,鎖超時。

結合圖3,引出幾個問題。

問題1如果有多個程序都去建立,只有乙個建立成功了,假設a建立成功了,bcd什麼時候去建立呢?

可以使用監聽機制,當節點失效的時候,都去競爭鎖。小於10個程序競爭的時候,可以使用這種方式;而如果有大量程序獲取鎖,就會驚群效應,浪費網路資源。

問題2來自問題1,如何解決驚群問題?

可以採用公平鎖:

1)建立節點,產生短暫順序節點。比如abcd依次建立,得到的短暫順序節點0、1、2、3。

2)每乙個程序都有乙個序號 。 假設序號為0,就是它獲取鎖;假設序號不為0,只需要監聽比它小一節的節點即可。

比如:b節點監聽a節點,只要a釋放,b就能拿到鎖。以此類推:c監聽b節點,d監聽c節點。

問題3來自問題2,程序a當前獲取到鎖,如果程序b崩潰,程序c如何能拿到鎖?

改為程序c監聽程序a。

分布式鎖實現原理

拜託,面試請不要再問我redis分布式鎖的實現原理!石杉的架構筆記 可重入鎖 為什麼不建議使用redis分布鎖 主從切換可能丟失鎖資訊 考慮一下這樣的場景 在分布式環境中,很多併發需要鎖來同步,當使用redis分布式鎖,通用的做法是使用redis的setnx key value px 這樣的命令,設...

分布式鎖 哨兵模式 分布式鎖實現原理

背景 記錄對分布式鎖的相關理解,不斷提公升自己 可重入鎖 為什麼不建議使用redis分布鎖 主從切換可能丟失鎖資訊 考慮一下這樣的場景 在分布式環境中,很多併發需要鎖來同步,當使用redis分布式鎖,通用的做法是使用redis的setnx key value px 這樣的命令,設定乙個字段,當設定成...

redisson實現分布式鎖原理

之前的基於註解的鎖有一種鎖是基本redis的分布式鎖,鎖的實現我是基於redisson元件提供的rlock,這篇來看看redisson是如何實現鎖的。引用的redisson最近發布的版本3.2.3,不同的版本可能實現鎖的機制並不相同,早期版本好像是採用簡單的setnx,getset等常規命令來配置完...