真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java分布式鎖的使用方案有哪些-創(chuàng)新互聯(lián)

這篇文章主要講解了“Java分布式鎖的使用方案有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java分布式鎖的使用方案有哪些”吧!

創(chuàng)新互聯(lián)主營(yíng)臨河網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都app軟件開(kāi)發(fā),臨河h5小程序定制開(kāi)發(fā)搭建,臨河網(wǎng)站營(yíng)銷(xiāo)推廣歡迎臨河等地區(qū)企業(yè)咨詢(xún)

前言

隨著互聯(lián)網(wǎng)技術(shù)的不斷發(fā)展,數(shù)據(jù)量的不斷增加,業(yè)務(wù)邏輯日趨復(fù)雜,在這種背景下,傳統(tǒng)的集中式系統(tǒng)已經(jīng)無(wú)法滿(mǎn)足我們的業(yè)務(wù)需求,分布式系統(tǒng)被應(yīng)用在更多的場(chǎng)景,而在分布式系統(tǒng)中訪(fǎng)問(wèn)共享資源就需要一種互斥機(jī)制,來(lái)防止彼此之間的互相干擾,以保證一致性,在這種情況下,我們就需要用到分布式鎖。

分布式一致性問(wèn)題

首先我們先來(lái)看一個(gè)小例子:

假設(shè)某商城有一個(gè)商品庫(kù)存剩10個(gè),用戶(hù)A想要買(mǎi)6個(gè),用戶(hù)B想要買(mǎi)5個(gè),在理想狀態(tài)下,用戶(hù)A先買(mǎi)走了6了,庫(kù)存減少6個(gè)還剩4個(gè),此時(shí)用戶(hù)B應(yīng)該無(wú)法購(gòu)買(mǎi)5個(gè),給出數(shù)量不足的提示;而在真實(shí)情況下,用戶(hù)A和B同時(shí)獲取到商品剩10個(gè),A買(mǎi)走6個(gè),在A更新庫(kù)存之前,B又買(mǎi)走了5個(gè),此時(shí)B更新庫(kù)存,商品還剩5個(gè),這就是典型的電商“秒殺”活動(dòng)。

從上述例子不難看出,在高并發(fā)情況下,如果不做處理將會(huì)出現(xiàn)各種不可預(yù)知的后果。那么在這種高并發(fā)多線(xiàn)程的情況下,解決問(wèn)題最有效最普遍的方法就是給共享資源或?qū)蚕碣Y源的操作加一把鎖,來(lái)保證對(duì)資源的訪(fǎng)問(wèn)互斥。在Java JDK已經(jīng)為我們提供了這樣的鎖,利用ReentrantLcok或者synchronized,即可達(dá)到資源互斥訪(fǎng)問(wèn)的目的。但是在分布式系統(tǒng)中,由于分布式系統(tǒng)的分布性,即多線(xiàn)程和多進(jìn)程并且分布在不同機(jī)器中,這兩種鎖將失去原有鎖的效果,需要我們自己實(shí)現(xiàn)分布式鎖——分布式鎖。

分布式鎖需要具備哪些條件

  1. 獲取鎖和釋放鎖的性能要好

  2. 判斷是否獲得鎖必須是原子性的,否則可能導(dǎo)致多個(gè)請(qǐng)求都獲取到鎖

  3. 網(wǎng)絡(luò)中斷或宕機(jī)無(wú)法釋放鎖時(shí),鎖必須被清楚,不然會(huì)發(fā)生死鎖

  4. 可重入一個(gè)線(xiàn)程中可以多次獲取同一把鎖,比如一個(gè)線(xiàn)程在執(zhí)行一個(gè)帶鎖的方法,該方法中又調(diào)用了另一個(gè)需要相同鎖的方法,則該線(xiàn)程可以直接執(zhí)行調(diào)用的方法,而無(wú)需重新獲得鎖;

5.阻塞鎖和非阻塞鎖,阻塞鎖即沒(méi)有獲取到鎖,則繼續(xù)等待獲取鎖;非阻塞鎖即沒(méi)有獲取到鎖后,不繼續(xù)等待,直接返回鎖失敗。

分布式鎖實(shí)現(xiàn)方式

一、數(shù)據(jù)庫(kù)鎖

一般很少使用數(shù)據(jù)庫(kù)鎖,性能不好并且容易產(chǎn)生死鎖。

  1. 基于MySQL鎖表

該實(shí)現(xiàn)方式完全依靠數(shù)據(jù)庫(kù)唯一索引來(lái)實(shí)現(xiàn),當(dāng)想要獲得鎖時(shí),即向數(shù)據(jù)庫(kù)中插入一條記錄,釋放鎖時(shí)就刪除這條記錄。這種方式存在以下幾個(gè)問(wèn)題:

(1) 鎖沒(méi)有失效時(shí)間,解鎖失敗會(huì)導(dǎo)致死鎖,其他線(xiàn)程無(wú)法再獲取到鎖,因?yàn)槲ㄒ凰饕齣nsert都會(huì)返回失敗。

(2) 只能是非阻塞鎖,insert失敗直接就報(bào)錯(cuò)了,無(wú)法進(jìn)入隊(duì)列進(jìn)行重試

(3) 不可重入,同一線(xiàn)程在沒(méi)有釋放鎖之前無(wú)法再獲取到鎖

  1. 采用樂(lè)觀鎖增加版本號(hào)

根據(jù)版本號(hào)來(lái)判斷更新之前有沒(méi)有其他線(xiàn)程更新過(guò),如果被更新過(guò),則獲取鎖失敗。

二、緩存鎖

具體實(shí)例可以參考我講述Redis的系列文章,里面有完整的Redis分布式鎖實(shí)現(xiàn)方案

這里我們主要介紹幾種基于redis實(shí)現(xiàn)的分布式鎖:

  1. 基于setnx、expire兩個(gè)命令來(lái)實(shí)現(xiàn)

基于setnx(set if not exist)的特點(diǎn),當(dāng)緩存里key不存在時(shí),才會(huì)去set,否則直接返回false。如果返回true則獲取到鎖,否則獲取鎖失敗,為了防止死鎖,我們?cè)儆胑xpire命令對(duì)這個(gè)key設(shè)置一個(gè)超時(shí)時(shí)間來(lái)避免。但是這里看似完美,實(shí)則有缺陷,當(dāng)我們setnx成功后,線(xiàn)程發(fā)生異常中斷,expire還沒(méi)來(lái)的及設(shè)置,那么就會(huì)產(chǎn)生死鎖。

解決上述問(wèn)題有兩種方案

第一種是采用redis2.6.12版本以后的set,它提供了一系列選項(xiàng)

EX seconds – 設(shè)置鍵key的過(guò)期時(shí)間,單位時(shí)秒

PX milliseconds – 設(shè)置鍵key的過(guò)期時(shí)間,單位時(shí)毫秒

NX – 只有鍵key不存在的時(shí)候才會(huì)設(shè)置key的值

XX – 只有鍵key存在的時(shí)候才會(huì)設(shè)置key的值

第二種采用setnx(),get(),getset()實(shí)現(xiàn),大體的實(shí)現(xiàn)過(guò)程如下:

(1) 線(xiàn)程Asetnx,值為超時(shí)的時(shí)間戳(t1),如果返回true,獲得鎖。

(2) 線(xiàn)程B用get 命令獲取t1,與當(dāng)前時(shí)間戳比較,判斷是否超時(shí),沒(méi)超時(shí)false,如果已超時(shí)執(zhí)行步驟3

(3) 計(jì)算新的超時(shí)時(shí)間t2,使用getset命令返回t3(這個(gè)值可能其他線(xiàn)程已經(jīng)修改過(guò)),如果t1==t3,獲得鎖,如果t1!=t3說(shuō)明鎖被其他線(xiàn)程獲取了

(4) 獲取鎖后,處理完業(yè)務(wù)邏輯,再去判斷鎖是否超時(shí),如果沒(méi)超時(shí)刪除鎖,如果已超時(shí),不用處理(防止刪除其他線(xiàn)程的鎖)

  1. RedLock算法

redlock算法是redis作者推薦的一種分布式鎖實(shí)現(xiàn)方式,算法的內(nèi)容如下:

(1) 獲取當(dāng)前時(shí)間;

(2) 嘗試從5個(gè)相互獨(dú)立redis客戶(hù)端獲取鎖;

(3) 計(jì)算獲取所有鎖消耗的時(shí)間,當(dāng)且僅當(dāng)客戶(hù)端從多數(shù)節(jié)點(diǎn)獲取鎖,并且獲取鎖的時(shí)間小于鎖的有效時(shí)間,認(rèn)為獲得鎖;

(4) 重新計(jì)算有效期時(shí)間,原有效時(shí)間減去獲取鎖消耗的時(shí)間;

(5) 刪除所有實(shí)例的鎖

redlock算法相對(duì)于單節(jié)點(diǎn)redis鎖可靠性要更高,但是實(shí)現(xiàn)起來(lái)?xiàng)l件也較為苛刻。

(1) 必須部署5個(gè)節(jié)點(diǎn)才能讓Redlock的可靠性更強(qiáng)。

(2) 需要請(qǐng)求5個(gè)節(jié)點(diǎn)才能獲取到鎖,通過(guò)Future的方式,先并發(fā)向5個(gè)節(jié)點(diǎn)請(qǐng)求,再一起獲得響應(yīng)結(jié)果,能縮短響應(yīng)時(shí)間,不過(guò)還是比單節(jié)點(diǎn)redis鎖要耗費(fèi)更多時(shí)間。

然后由于必須獲取到5個(gè)節(jié)點(diǎn)中的3個(gè)以上,所以可能出現(xiàn)獲取鎖沖突,即大家都獲得了1-2把鎖,結(jié)果誰(shuí)也不能獲取到鎖,這個(gè)問(wèn)題,redis作者借鑒了raft算法的精髓,通過(guò)沖突后在隨機(jī)時(shí)間開(kāi)始,可以大大降低沖突時(shí)間,但是這問(wèn)題并不能很好的避免,特別是在第一次獲取鎖的時(shí)候,所以獲取鎖的時(shí)間成本增加了。

如果5個(gè)節(jié)點(diǎn)有2個(gè)宕機(jī),此時(shí)鎖的可用性會(huì)極大降低,首先必須等待這兩個(gè)宕機(jī)節(jié)點(diǎn)的結(jié)果超時(shí)才能返回,另外只有3個(gè)節(jié)點(diǎn),客戶(hù)端必須獲取到這全部3個(gè)節(jié)點(diǎn)的鎖才能擁有鎖,難度也加大了。

如果出現(xiàn)網(wǎng)絡(luò)分區(qū),那么可能出現(xiàn)客戶(hù)端永遠(yuǎn)也無(wú)法獲取鎖的情況,介于這種情況,下面我們來(lái)看一種更可靠的分布式鎖zookeeper鎖。

zookeeper分布式鎖

關(guān)于zookeeper的分布式鎖實(shí)現(xiàn)在之前講述zookeeper的時(shí)候已經(jīng)介紹了。這里不再贅述、

首先我們來(lái)了解一下zookeeper的特性,看看它為什么適合做分布式鎖,

zookeeper是一個(gè)為分布式應(yīng)用提供一致服務(wù)的軟件,它內(nèi)部是一個(gè)分層的文件系統(tǒng)目錄樹(shù)結(jié)構(gòu),規(guī)定統(tǒng)一個(gè)目錄下只能有一個(gè)唯一文件名。

數(shù)據(jù)模型:

永久節(jié)點(diǎn):節(jié)點(diǎn)創(chuàng)建后,不會(huì)因?yàn)闀?huì)話(huà)失效而消失

臨時(shí)節(jié)點(diǎn):與永久節(jié)點(diǎn)相反,如果客戶(hù)端連接失效,則立即刪除節(jié)點(diǎn)

順序節(jié)點(diǎn):與上述兩個(gè)節(jié)點(diǎn)特性類(lèi)似,如果指定創(chuàng)建這類(lèi)節(jié)點(diǎn)時(shí),zk會(huì)自動(dòng)在節(jié)點(diǎn)名后加一個(gè)數(shù)字后綴,并且是有序的。

監(jiān)視器(watcher):

當(dāng)創(chuàng)建一個(gè)節(jié)點(diǎn)時(shí),可以注冊(cè)一個(gè)該節(jié)點(diǎn)的監(jiān)視器,當(dāng)節(jié)點(diǎn)狀態(tài)發(fā)生改變時(shí),watch被觸發(fā)時(shí),ZooKeeper將會(huì)向客戶(hù)端發(fā)送且僅發(fā)送一條通知,因?yàn)閣atch只能被觸發(fā)一次。

根據(jù)zookeeper的這些特性,我們來(lái)看看如何利用這些特性來(lái)實(shí)現(xiàn)分布式鎖:

  1. 創(chuàng)建一個(gè)鎖目錄lock

  2. 希望獲得鎖的線(xiàn)程A就在lock目錄下,創(chuàng)建臨時(shí)順序節(jié)點(diǎn)

  3. 獲取鎖目錄下所有的子節(jié)點(diǎn),然后獲取比自己小的兄弟節(jié)點(diǎn),如果不存在,則說(shuō)明當(dāng)前線(xiàn)程順序號(hào)最小,獲得鎖

  4. 線(xiàn)程B獲取所有節(jié)點(diǎn),判斷自己不是最小節(jié)點(diǎn),設(shè)置監(jiān)聽(tīng)(watcher)比自己次小的節(jié)點(diǎn)(只關(guān)注比自己次小的節(jié)點(diǎn)是為了防止發(fā)生“羊群效應(yīng)”)

  5. 線(xiàn)程A處理完,刪除自己的節(jié)點(diǎn),線(xiàn)程B監(jiān)聽(tīng)到變更事件,判斷自己是最小的節(jié)點(diǎn),獲得鎖。

感謝各位的閱讀,以上就是“Java分布式鎖的使用方案有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java分布式鎖的使用方案有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


當(dāng)前名稱(chēng):Java分布式鎖的使用方案有哪些-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://weahome.cn/article/cdopgd.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部