分佈式系統核心要求:分佈式鎖的重要性及實現方式

線程安全告訴我們無狀態和原子類型是線程安全的,對於分佈式而言 我們的狀態修改只能一個入口並且是加鎖的,這樣才能保證在分佈式環境下數據的安全可靠。 

一、爲什麼要使用分佈式鎖

我們在開發應用的時候,如果需要對某一個共享變量進行多線程同步訪問的時候,可以使用我們學到的Java多線程的18般武藝進行處理,並且可以完美的運行,毫無Bug!

注意這是單機應用,也就是所有的請求都會分配到當前服務器的JVM內部,然後映射爲操作系統的線程進行處理!而這個共享變量只是在這個JVM內部的一塊內存空間!

後來業務發展,需要做集羣,一個應用需要部署到幾臺機器上然後做負載均衡,大致如下圖:

這裏寫圖片描述

上圖可以看到,變量A存在JVM1、JVM2、JVM3三個JVM內存中(這個變量A主要體現是在一個類中的一個成員變量,是一個有狀態的對象,例如:UserController控制器中的一個整形類型的成員變量),如果不加任何控制的話,變量A同時都會在JVM分配一塊內存,三個請求發過來同時對這個變量操作,顯然結果是不對的!即使不是同時發過來,三個請求分別操作三個不同JVM內存區域的數據,變量A之間不存在共享,也不具有可見性,處理的結果也是不對的!

如果我們業務中確實存在這個場景的話,我們就需要一種方法解決這個問題!

爲了保證一個方法或屬性在高併發情況下的同一時間只能被同一個線程執行,在傳統單體應用單機部署的情況下,可以使用Java併發處理相關的API(如ReentrantLock或Synchronized)進行互斥控制。在單機環境中,Java中提供了很多併發處理相關的API。但是,隨着業務發展的需要,原單體單機部署的系統被演化成分佈式集羣系統後,由於分佈式系統多線程、多進程並且分佈在不同機器上,這將使原單機部署情況下的併發控制鎖策略失效,單純的Java API並不能提供分佈式鎖的能力。爲了解決這個問題就需要一種跨JVM的互斥機制來控制共享資源的訪問,這就是分佈式鎖要解決的問題!

二、分佈式鎖應該具備哪些條件


在分析分佈式鎖的三種實現方式之前,先了解一下分佈式鎖應該具備哪些條件:

1、在分佈式系統環境下,一個方法在同一時間只能被一個機器的一個線程執行; 
2、高可用的獲取鎖與釋放鎖; 
3、高性能的獲取鎖與釋放鎖; 
4、具備可重入特性; 
5、具備鎖失效機制,防止死鎖; 
6、具備非阻塞鎖特性,即沒有獲取到鎖將直接返回獲取鎖失敗。

三、分佈式鎖的三種實現方式

目前幾乎很多大型網站及應用都是分佈式部署的,分佈式場景中的數據一致性問題一直是一個比較重要的話題。分佈式的CAP理論告訴我們“任何一個分佈式系統都無法同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),最多隻能同時滿足兩項。”所以,很多系統在設計之初就要對這三者做出取捨。在互聯網領域的絕大多數的場景中,都需要犧牲強一致性來換取系統的高可用性,系統往往只需要保證“最終一致性”,只要這個最終時間是在用戶可以接受的範圍內即可。

 
在很多場景中,我們爲了保證數據的最終一致性,需要很多的技術方案來支持,比如分佈式事務、分佈式鎖等。有的時候,我們需要保證一個方法在同一時間內只能被同一個線程執行。

  • 基於數據庫實現分佈式鎖; 
  • 基於緩存(Redis等)實現分佈式鎖; 
  • 基於Zookeeper實現分佈式鎖;

這三種方式對比:

從理解的難易程度角度(從低到高)

  • 數據庫 > 緩存 > Zookeeper

從實現的複雜性角度(從低到高)

  • Zookeeper >= 緩存 > 數據庫

從性能角度(從高到低)

  • 緩存 > Zookeeper >= 數據庫

從可靠性角度(從高到低)

  • Zookeeper > 緩存 > 數據庫

————————————————
版權聲明:本文爲CSDN博主「1Vincent」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/wuzhiwei549/article/details/80692278

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章