Java++:一文搞懂分佈式鎖及其業務場景

爲什麼用分佈式鎖?

在討論這個問題之前,我們先來看一個業務場景:

系統A是一個電商系統,目前是一臺機器部署,系統中有一個用戶下訂單的接口,但是用戶下訂單之前一定要去檢查一下庫存,確保庫存足夠了纔會給用戶下單。

由於系統有一定的併發,所以會預先將商品的庫存保存在redis中,用戶下單的時候會更新redis的庫存。

此時系統架構如下:

但是這樣一來會產生一個問題:

假如某個時刻,redis裏面的某個商品庫存爲1,此時兩個請求同時到來,其中一個請求執行到上圖的第3步,更新數據庫的庫存爲0,但是第4步還沒有執行。

而另外一個請求執行到了第2步,發現庫存還是1,就繼續執行第3步。

這樣的結果,是導致賣出了2個商品,然而其實庫存只有1個。

很明顯不對啊!這就是典型的庫存超賣問題 !!!

此時,我們很容易想到解決方案:

用鎖把2、3、4步鎖住,讓他們執行完之後,另一個線程才能進來執行第2步。

按照上面的圖,在執行第2步時,使用Java提供的synchronized或者ReentrantLock來鎖住,然後在第4步執行完之後才釋放鎖。

這樣一來,2、3、4 這3個步驟就被“鎖”住了,多個線程之間只能串行化執行。

但是好景不長,整個系統的併發飆升,一臺機器扛不住了。

現在要增加一臺機器,如下圖:

增加機器之後,系統變成上圖所示,我的天!

假設此時兩個用戶的請求同時到來,但是落在了不同的機器上,那麼這兩個請求是可以同時執行了,還是會出現庫存超賣的問題。

爲什麼呢?因爲上圖中的兩個A系統,運行在兩個不同的JVM裏面,他們加的鎖只對屬於自己JVM裏面的線程有效,對於其他JVM的線程是無效的。

因此,這裏的問題是:Java提供的原生鎖機制在多機部署場景下失效了。

這是因爲兩臺機器加的鎖不是同一個鎖(兩個鎖在不同的JVM裏面)。

那麼,我們只要保證兩臺機器加的鎖是同一個鎖,問題不就解決了嗎?

此時,就該分佈式鎖隆重登場了,分佈式鎖的思路是:

在整個系統提供一個全局、唯一的獲取鎖的“東西”,然後每個系統在需要加鎖時,都去問這個“東西”拿到一把鎖,這樣不同的系統拿到的就可以認爲是同一把鎖。

至於這個“東西”,可以是 Redis、Zookeeper,也可以是數據庫。

文字描述不太直觀,我們來看下圖:

通過上面的分析,我們知道了庫存超賣場景在分佈式部署系統的情況下使用Java原生的鎖機制無法保證線程安全,所以我們需要用到分佈式鎖的方案。

那麼,如何實現分佈式鎖呢?接着往下看!

待更新....

 

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