Java中单体应用锁的局限性&分布式锁
互聯(lián)網(wǎng)系統(tǒng)架構(gòu)的演進
在互聯(lián)網(wǎng)系統(tǒng)發(fā)展之初,系統(tǒng)比較簡單,消耗資源小,用戶訪問量也比較少,我們只部署一個Tomcat應用就可以滿足需求。系統(tǒng)架構(gòu)圖如下:
一個Tomcat可以看作是一個JVM進程,當大量的請求并發(fā)到達系統(tǒng)時,所有的請求都落在這唯一的一個Tomcat上,如果某些請求方法是需要加鎖的,比如:秒殺扣減庫存,是可以滿足需求的,這和我們前面章節(jié)所講的內(nèi)容是一樣的。但是隨著訪問量的增加,導致一個Tomcat難以支撐,這時我們就要集群部署Tomcat,使用多個Tomcat共同支撐整個系統(tǒng)。系統(tǒng)架構(gòu)圖如下:
上圖中,我們部署了兩個Tomcat,共同支撐系統(tǒng)。當一個請求到達系統(tǒng)時,首先會經(jīng)過Nginx,Nginx主要是做負載轉(zhuǎn)發(fā)的,它會根據(jù)自己配置的負載均衡策略將請求轉(zhuǎn)發(fā)到其中的一個Tomcat中。當大量的請求并發(fā)訪問時,兩個Tomcat共同承擔所有的訪問量,這時,我們同樣在秒殺扣減庫存的場景中,使用單體應用鎖,還能夠滿足要求嗎?
單體應用鎖的局限性
如上圖所示,在整個系統(tǒng)架構(gòu)中,存在兩個Tomcat,每個Tomcat是 -個JVM。在進行秒殺業(yè)務的時候,由于大家都在搶購秒殺商品,大量的請求同時到達系統(tǒng),通過Nginx分 發(fā)到兩個Tomcat上。我們通過一個極端的案例場景, 可以更好地理解單體應用鎖的局限性。假如,秒殺商品的數(shù)量只有1個,這時,這些大量的請求當中,只有一個請求可以成功的搶到這個商品,這就需要在扣減庫存的方法.上加鎖,扣減庫存的動作只能一個一個去執(zhí)行,而不能同時去執(zhí)行如果同時執(zhí)行,這1個商品可能同時被多個人搶到,從而產(chǎn)生超賣現(xiàn)象。加鎖之后,扣減庫存的動作一個一個去執(zhí)行,凡是將庫存扣減為負數(shù)的,都拋出異常,提示該用戶沒有搶到商品。通過加鎖看似解決了秒殺的問題,但是事實,上真的是這樣嗎?
我們看到系統(tǒng)中存在兩個Tomcat,我們加的鎖是JDK提供的鎖,這種鎖只能在一個JVM下起作用,也就是在一個Tomcat內(nèi)是沒有問題的。當存在兩個或兩個以上的Tomcat時,大量的并發(fā)請求分散到不同的Tomcat_上,在每一一個Tomcat中都可以防止并發(fā)的產(chǎn)生,但是在多個Tomcat之間,每個Tomcat中獲得鎖的這個請求,又產(chǎn)生了并發(fā)從而產(chǎn)生超賣現(xiàn)象。這也就是單體應用鎖的局限性,它只能在一個JVM內(nèi)加鎖,而不能從這個應用層面去加鎖。
那么這個問題如何解決呢?這就需要使用分布式鎖了,在整個應用層面去加鎖。什么是分布式鎖呢?我們怎么去使用分布式鎖呢?
什么是分布式鎖
在說分布式鎖之前,我們看一看單體應用鎖的特點,單體應用鎖是在一個JVM進程內(nèi)有效,無法跨JVM、跨進程。那么分布式鎖的定義就出來了,分布式鎖就是可以跨越多個JVM、跨越多個進程的鎖,這種鎖就叫做分布式鎖。
分布式鎖的設計思路
在上圖中,由于Tomcat是由Java啟動的,所以每個Tomcat可以看成一個JVM,JVM內(nèi)部的鎖是無法跨越多個進程的。所以,我們要實現(xiàn)分布式鎖,我們只能在這些JVM之外去尋找,通過其他的組件來實現(xiàn)分布式鎖。系統(tǒng)的架構(gòu)如圖所示:
兩個Tomcat通過第三方的組件實現(xiàn)跨JVM、跨進程的分布式鎖。這就是分布式鎖的解決思路,找到所有JVM可以共同訪問的第三方組件,通過第三方組件實現(xiàn)分布式鎖。
目前存在的分布式的方案
分布式鎖都是通過第三方組件來實現(xiàn)的,目前比較流行的分布式鎖的解決方案有:
- 數(shù)據(jù)庫,通過數(shù)據(jù)庫可以實現(xiàn)分布式鎖,但是在高并發(fā)的情況下對數(shù)據(jù)庫壓力較大,所以很少使用。
- Redis,借助Redis也可以實現(xiàn)分布式鎖,而且Redis的Java客戶端種類很多,使用的方法也不盡相同。
- Zookeeper,Zookeeper也可以實現(xiàn)分布式鎖,同樣Zookeeper 也存在多個Java客戶端,使用方法也不相同。
本人最近搭建了程序員專屬的編程資料個人網(wǎng)站:程序員波特,主要記錄Java相關技術系列教程,面試題的收集和整理等,讓上班摸魚的你,不再無聊。
總結(jié)
以上是生活随笔為你收集整理的Java中单体应用锁的局限性&分布式锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Blazor入门100天 : 身份验证和
- 下一篇: 背会了常见的几个线程池用法,结果被问翻了