-
1 # 此生唯一
-
2 # 會點程式碼的大叔
分散式鎖也是鎖
在單體應用的時候,如果多個執行緒要訪問共享資源的時候,我們通常執行緒間加鎖的機制,在某一個時刻,只有一個執行緒可以對這個資源進行操作,其他執行緒需要等待鎖的釋放,Java中也有一些處理鎖的機制,比如synchronized。
而到了分散式的環境中,當某個資源可以被多個系統訪問使用到的時候,為了保證大家訪問這個資料是一致性的,那麼就要求再同一個時刻,只能被一個系統使用,這時候執行緒之間的鎖機制就無法起到作用了,因為分散式環境中,系統是會部署到不同的機器上面的,那麼就需要【分散式鎖】了。
什麼時候需要使用分散式鎖總結來看,當有多個客戶端需要訪問並操作同一個資源,還需要保持這個資源一致性的時候,就需要使用【分散式鎖】,讓多客戶端互斥的對共享資源進行訪問。
舉個例子來說明一下:
有多個批處理任務,兩臺機器同時處理,如果不加任何控制的話,很有可能同一個批處理被兩臺機器分別處理一遍;如果使用分散式鎖,在領取任務的時候,一個任務只會被一臺機器領到,這樣就不會造成任務的重複執行;再多思考一些,如果A/B兩臺機器,任務1被A機器領取到進行處理,在處理到一半的時候,A機器掛掉了,那麼這個批處理任務也就無法順利執行了,除非A機器可以恢復。
-
3 # 一個存在感小透明
作為BAT的Java web開發工程師來回答這個問題。
分散式鎖是目前Java web開發過程中常見的一個情況,接下來,我從場景以及如何實現兩個維度來分析。
使用場景當你的後端服務是以叢集形式存在的時候,是一定需要分散式鎖的。叢集與分散式不同,而這裡的分散式與分散式鎖也不是同一回事兒。叢集可以指多臺伺服器實現了同樣的需求,比如有三臺Tomcat,都負責查詢模組;而分散式指多臺伺服器各自不同的功能點,多臺功能的整合對外是一個完整的服務,比如一臺Tomcat負責查詢,一臺負責下單。
說回叢集,當後端叢集要去訪問同一個資源的時候,就需要對該資源加鎖,保證同一時刻只能有一個物件來修改該資源資料,如果不加鎖會導致什麼情況呢?
舉一個例子:
有兩個執行緒(分別叫T1,T2)做的都是同樣的事情,拿到一個叫做A的資源,然後對其進行+1操作。由於執行緒之間是不會互相通訊的,於是就有可能出現下面這種情況:
T1拿到A,讀入記憶體,此時A值為T;
T2拿到A,讀入記憶體,此時A值為T;
T1進行+1操作,此時A實際值為T+1;
T2進行+1操作,此時A的實際值仍然為T+1;
然而,此時A經過兩個執行緒執行+1操作,應該為T+2才對的,所以可以看出,如果沒有分散式鎖,就會出現資料不一致的問題。如果是上面這種簡單的計算還好,如果是你的銀行賬戶,沒用分散式鎖,此時有兩個人給你打錢,結果只有其中一個人的到賬了,另一個人的被作為無主錢財被銀行充公了,肯定是不行的吧。
所以,保障資料一致性和準確性就是分散式鎖的重要性。
如何實現在這裡可以給大家介紹一個用redis來實現分散式鎖的方案。
Redis對外開放了一個非常厲害的api,目前經常被大家用來做分散式鎖,是絕對的執行緒安全,這個函式就是SET key field value加上NX引數。這個NX引數可是了不得,通常來說,set函式是不管field欄位是否存在,只要寫入成功就會返回1,但是如果增加了NX引數,那麼如果field值在redis中已經存在,就會返回nil,否則才返回1。因此可以透過這個函式來執行加鎖操作,如果返回值不為nil,則加鎖成功,否則代表有其他執行緒在操作資料,當前請求需要等待。
不僅如此,為了避免死鎖,SET還有一個引數為EX,即EX毫秒後,field會自動清空。
此外,還有PX,XX引數,具體含義見如下文件。
回覆列表
首先需要知道非分散式環境下,用鎖可以解決什麼?
多執行緒環境下,共享資源的執行緒安全問題!這個時候的共享資源通常是在單機裡面的多執行緒裡存在競爭,從JAVA記憶體模型來看,可以透過鎖住物件,鎖住方法,鎖住程式碼塊等方式,避免共享資源的競爭!
而在分散式環境中,共享資源所要經過的程式碼,方法,都不是在一個JVM裡面,也不是同一個程序!透過鎖方法,程式碼塊的方式不能解決共享資源的競爭,需要分散式的鎖!
分散式鎖通常在以下場景中使用:
1,全域性ID的生成;
2,全域性配置檔案的修改;
3,分散式服務中的秒殺問題;
4,分散式環境下的重複提交;
分散式鎖通常有以下實現方式:
1,使用資料庫的唯一主鍵來實現鎖!
2,使用redis的指令:通常使用setnx方法,incr方法等進行實現
3,使用zookeeper:使用api生成臨時節點實現鎖!
最近在持續分享JAVA相關技術,有很多幹貨,敬請關注。。