分散式鎖

zhegeMaw發表於2024-08-13

網際網路的應用場景中,為了支援高併發的請求,服務都是執行的分散式部署(相同的任務可以在叢集中不同的伺服器上執行)並且現在的服務容器都是支援多執行緒,相同的任務也可能會被同一個容器多次執行,都要求執行結果都滿足冪等性的設計原則。

分散式鎖,就是為了確保在分散式的環境下,相同任務只會執行成功的執行一次,後續的執行不會對這些已經產生了變化的業務再次產生影響。

一、是否有必要加鎖

如果對精度要求不高,可不可以不加鎖

二、加鎖方式

1. 資料庫加鎖

2. 基於Redis的分散式鎖

3. 基於ZooKeeper的分散式鎖。

2.1 基於Redis實現分散式鎖

  • 方案://todo

  • 缺點:阻塞問題(未獲得鎖的執行緒阻塞,一直等待,導致系統併發效能降低)

    資料庫主從延遲(對於讀寫分離的資料庫,寫到主庫,讀為從庫,主庫和從庫之間的資料同步存在延遲,當資料未及時同步時,會導致讀取到的資料不是最新的)

  • 基於Redis 實現分散式鎖的一些問題

    • 在高併發下的分散式鎖實現中,key的過期肯定不能設定的太長,否則會影響後續執行緒持有該鎖;

    • 但是如果設定過期時間很短,直到key過期,持有該鎖的執行緒還未執行完任務;接著下一個執行緒獲取到該鎖,這時候前一個執行緒執行完成後觸發del釋放該鎖,而這把鎖這個時候其實是另外一個執行緒持有;

    • 獲取鎖是非阻塞的,無論成功還是失敗就直接返回;

    • 鎖公平問題,所有等待執行緒同時發起獲取鎖命令操作。

    針對上述問題需要另外服務來保證實現:

    1. 守護執行緒:如果某個執行緒在expire時間內,還未執行完成,守護執行緒自動expire一個新過期時間,直到該執行緒執行完成或釋放;

    2. 釋放驗證:執行緒加鎖前透過執行緒ID和Key Value匹配,釋放前透過兩者判斷是否一致,一致再釋放該鎖,避免錯誤釋放其他執行緒執行時持有相同的鎖(原子性可以透過lua指令碼來實現);

    3. 阻塞鎖: 透過while true之類的機制去阻塞程式碼實現;

    4. 公平鎖:可以透過將所有等待執行緒放入同一個佇列來實現。

參考資料

叢集環境中使用Redis實現分散式鎖兩種方式

普通鎖和分散式鎖

相關文章