淺談分散式鎖--簡介篇
淺談分散式鎖--簡介篇
1、什麼是分散式鎖(分散式系統用到的鎖):
分散式鎖,是單機鎖的一種擴充套件,主要是為了鎖住分散式系統中不同機器程式碼的物理塊或邏輯塊。以此保證不同機器之間的邏輯一致性。
在叢集等多伺服器中經常使用到同步處理一下業務,這是普通的事務是滿足不了業務需求,需要分散式鎖。
分散式鎖是控制分散式系統或不同系統之間共同訪問共享資源的一種鎖實現,如果不同的系統或同一個系統的不同主機之間共享了某個資源時,往往需要互斥來防止彼此干擾來保證一致性。
2、分散式鎖需要解決的問題:
1、互斥性:任意時刻,只能有一個客戶端獲取鎖,不能同時有兩個客戶端獲取到鎖。
2、安全性:鎖只能被持有該鎖的客戶端刪除,不能由其它客戶端刪除。
3、死鎖:獲取鎖的客戶端因為某些原因(如down機等)而未能釋放鎖,其它客戶端再也無法獲取到該鎖。
4、容錯:當部分節點(redis節點等)down機時,客戶端仍然能夠獲取鎖和釋放鎖。
3、分散式鎖場景:
目前很多大型網站及應用都是分散式部署的,分散式場景中的資料一致性問題一直是一個比較重要的話題。
分散式的CAP理論告訴我們“任何一個分散式系統都無法同時滿足一致性(Consistency)、可用性(Availability)和分割槽容錯性(Partition tolerance),最多隻能同時滿足兩項。所以,很多系統在設計之初就要對這三者做出取捨。在網際網路領域的絕大多數的場景中,都需要犧牲強一致性來換取系統的高可用性,系統往往只需要保證“最終一致性”,只要這個最終時間是在使用者可以接受的範圍內即可。
在很多場景中,我們為了保證資料的最終一致性,需要很多的技術方案來支援,比如分散式事務、分散式鎖等。有的時候,我們需要保證一個方法在同一時間內只能被同一個執行緒執行。
在單機環境中,Java中其實提供了很多併發處理相關的API,但是這些API在分散式場景中就無能為力了。
也就是說單純的Java Api並不能提供分散式鎖的能力。所以針對分散式鎖的實現目前有多種方案。
4、分散式鎖的實現,目前比較常用的有以下幾種方案:
基於資料庫實現分散式鎖
基於快取(redis,memcached,tair)實現分散式鎖
基於Zookeeper實現分散式鎖
5、分散式鎖的設計應該是怎麼樣的?
可以保證在分散式部署的應用叢集中,同一個方法在同一時間只能被一臺機器上的一個執行緒執行。
這把鎖要是一把可重入鎖(避免死鎖)。
這把鎖最好是一把阻塞鎖。
有高可用的獲取鎖和釋放鎖功能。
獲取鎖和釋放鎖的效能要好。
具備鎖失效機制,防止死鎖。
6、分散式鎖實現原理總結:
6.1 分散式鎖的實現(主要涉及那些東西,有3方面)
1.如何獲取到鎖。
2.如何釋放得到的鎖。
3.如何得知鎖被釋放了。
6.2 如何獲取到鎖
能夠提供一種方式,多個客戶端併發操作,只能有一個客戶端能滿足相應的要求,獲得相應的鎖。
資料庫的for update的sql語句、或者插入一個含有唯一約束的資料等。
redis的setnx等。
ZooKeeper的求最小節點的方式。
這些都可以保證只能有一個客戶端獲取到了鎖。
6.3 如何釋放得到的鎖
場景一般有2種情況:
1 正常情況下的釋放鎖
2 異常情況下如何釋放鎖(即釋放鎖的操作沒有被執行,如掛掉、沒執行成功等原因)
資料庫在查詢語句後面增加for update,資料庫會在查詢過程中給資料庫表增加排他鎖,通過connection.commit()操作來釋放鎖。使用這種方式,服務宕機之後資料庫會自己把鎖釋放掉。
redis正常情況下釋放鎖是刪除lock_key,異常情況下,只能通過lock_key的超時時間了。
ZooKeeper正常情況下釋放鎖是刪除臨時節點,異常情況下,伺服器也會主動刪除臨時節點。
6.4 如何得知鎖被釋放了
實現方式一般有2種情況:
1 沒有獲取到鎖的客戶端不斷嘗試獲取鎖(迴圈等待,比較浪費資源)。
2 伺服器端通知客戶端鎖被釋放了。
第二種情況是最優的(客戶端所做的無用功最少),如ZooKeeper通過註冊watcher來得到鎖釋放的通知。
而資料庫、redis沒有辦法來通知客戶端鎖釋放了,那客戶端就只能傻傻的不斷嘗試獲取鎖了。
7、分散式鎖實現方式優缺點:
資料庫鎖:
優點:直接使用資料庫,使用簡單。
缺點:分散式系統大多數瓶頸都在資料庫,使用資料庫鎖會增加資料庫負擔。
快取鎖(redis,memcached,tair):
優點:效能高,實現起來較為方便,在允許偶發的鎖失效情況,不影響系統正常使用,建議採用快取鎖。
缺點:通過鎖超時機制不是十分可靠,當執行緒獲得鎖後,處理時間過長導致鎖超時,就失效了鎖的作用。
zookeeper鎖:
優點:不依靠超時時間釋放鎖;可靠性高;系統要求高可靠性時,建議採用zookeeper鎖。
缺點:效能比不上快取鎖,因為要頻繁的建立節點刪除節點。