亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

分布式鎖和我們平常講到的鎖原理基本一樣,目的就是確保在多個線程并發(fā)時,只有一個線程在同一刻操作這個業(yè)務或者說方法、變量。

在一個進程中,也就是一個jvm或者說應用中,我們很容易去處理控制,在jdk JAVA.util并發(fā)包中已經為我們提供了這些方法去加鎖,比如synchronized關鍵字或者Lock鎖,都可以處理。

但是我們現在的應用程序如果只部署一臺服務器,那并發(fā)量是很差的,如果同時有上萬的請求,很有可能造成服務器壓力過大而癱瘓。想想雙十一和大年三十晚上十點,瓜分支付寶紅包等業(yè)務場景,自然需要用到多臺服務器去同時處理這些業(yè)務,這些服務可能會有上百臺同時處理。

但是我們想一想,如果有100臺服務器要處理分紅包的業(yè)務,現在假設有1億的紅包,1千萬個人分,金額隨機,那么這個業(yè)務場景下,是不是必須確保這1千萬個人最后分的紅包金額總和等于1億?

 

一、常規(guī)鎖會造成什么情況?

首先說一下我們?yōu)槭裁匆慵骸?/p>

簡單理解就是,需求量(請求并發(fā)量)變大了,一個工人處理能力有限,那就多招一些工人來一起處理。

假設1千萬個請求平均分配到100臺服務器上,每個服務器接收10w的請求。這10w個請求并不是在同一秒中來的,可能是在1,2個小時內,可以聯想下我們三十晚上開紅包,等到10:20開始,有的人立馬開了,有的人等到12點才想起來。

那這樣的話,平均到每一秒上的請求也就不到1千個,這種壓力一般的服務器還是可以承受的。

  • 第一個用戶來分,請求到來后,需要在1億里面給他分一部分錢,金額隨機,假設第一個人分到了100,那就要在這1億中減去100塊,剩下99999900塊~
  • 第二個用戶再來分,金額隨機,這次分200塊,那就需要在剩下的99999900塊中再減去200塊,剩下99999700塊。
  • 等到第10w個用戶來,一看還有1000w,那這1000w全成他的了。

 

等于是在每個服務器中去分1億,也就是10w個用戶分了一個億,最后總計有100個服務器,要分100億。

如果真這樣了,那分紅包的開發(fā)項目組,以及產品經理,可以GG了~

簡化結構圖如下:

 

分布式鎖通俗解讀

 

二、分布式鎖怎么去處理?

那么為了解決這個問題,讓1000萬用戶只分1億,而不是100億,這個時候分布式鎖就派上用處了。

分布式鎖可以把整個集群就當作是一個應用一樣去處理,那么也就需要這個鎖獨立于每一個服務之外,而不是在服務里面。

假設第一個服務器接收到用戶1的請求后,不能只在自己的應用中去判斷還有多少錢可以分了,而需要去外部請求專門負責管理這1億紅包的人(服務),問他:哎,我這里要分100塊,給我100。

管理紅包的妹子(服務)一看,還有1個億,那好,給你100塊,然后剩下99999900塊。

第二個請求到來后,被服務器2獲取,繼續(xù)去詢問,管理紅包的妹子,我這邊要分10塊,管理紅包的妹子先查了下還有99999900,那就說:好,給你10塊。那就剩下99999890塊。

等到第1000w個請求到來后,服務器100拿到請求,繼續(xù)去詢問,管理紅包的妹子,我要100,妹子翻了翻白眼,對你說,就剩1塊了,愛要不要,那這個時候就只能給你1塊了(1塊也是錢啊,買根辣條還是可以的)。

這些請求編號1,2不代表執(zhí)行的先后順序,正式的場景下,應該是100臺服務器每個服務器持有一個請求去訪問負責管理紅包的妹子(服務),那在管紅包的妹子那里同時會接收到100個請求,這個時候就需要在負責紅包的妹子那里加個鎖就可以了(拋繡球),你們100個服務器誰拿到鎖(搶到繡球),誰就進來和我談,我給你分,其他人就等著去吧。

簡化的結構圖如下:

 

分布式鎖通俗解讀

 

三、分布式鎖的實現有哪些?

說到分布式鎖的實現,還是有很多的,有數據庫方式的,有redis分布式鎖,有Zookeeper分布式鎖等等。

我們如果采用Redis作為分布式鎖,那么上圖中負“責紅包的妹子(服務)”,就可以替換成Redis,請自行腦補。

1、為什么Redis可以實現分布式鎖?

首先Redis是單線程的,這里的單線程指的是網絡請求模塊使用了一個線程(所以不需考慮并發(fā)安全性),即一個線程處理所有網絡請求,其他模塊仍用了多個線程。

在實際的操作中過程大致是這樣子的:

服務器1要去訪問發(fā)紅包的妹子,也就是Redis,那么他會在Redis中通過"setnx key value" 操作設置一個key進去,value是啥不重要,重要的是要有一個key,也就是一個標記,而且這個key你愛叫啥叫啥,只要所有的服務器設置的key相同就可以。

假設我們設置一個,如下圖:

 

分布式鎖通俗解讀

 

那么我們可以看到會返回一個1,那就代表了成功。

如果再來一個請求去設置同樣的key,如下圖:

 

分布式鎖通俗解讀

 

這個時候會返回0,那就代表失敗了。

那么我們就可以通過這個操作去判斷是不是當前可以拿到鎖,或者說可以去訪問“負責發(fā)紅包的妹子”,如果返回1,那我就開始去執(zhí)行后面的邏輯,如果返回0,那就說明已經被人占用了,我就要繼續(xù)等待。

當服務器1拿到鎖之后,進行了業(yè)務處理,完成后,還需要釋放鎖,如下圖所示:

 

分布式鎖通俗解讀

 

刪除成功返回1,那么其他的服務器就可以繼續(xù)重復上面的步驟去設置這個key,以達到獲取鎖的目的。

當然以上的操作是在Redis客戶端直接進行的,通過程序調用的話,肯定就不能這么寫,比如java就需要通過jedis去調用,但是整個處理邏輯基本都是一樣的。

通過上面的方式,我們好像是解決了分布式鎖的問題,但是想想還有沒有什么問題呢?

對,問題還是有的,可能會有死鎖的問題發(fā)生,比如服務器1設置完之后,獲取了鎖之后,忽然發(fā)生了宕機。那后續(xù)的刪除key操作就沒法執(zhí)行,這個key會一直在Redis中存在,其他服務器每次去檢查,都會返回0,他們都會認為有人在使用鎖,我需要等。

為了解決這個死鎖的問題,我們就需要給key設置有效期了。

設置的方式有2種:

  • 第一種就是在set完key之后,直接設置key的有效期 "expire key timeout" ,為key設置一個超時時間,單位為second,超過這個時間鎖會自動釋放,避免死鎖。

這種方式相當于,把鎖持有的有效期,交給了Redis去控制。如果時間到了,你還沒有給我刪除key,那Redis就直接給你刪了,其他服務器就可以繼續(xù)去setnx獲取鎖。

  • 第二種方式,就是把刪除key權利交給其他的服務器,那這個時候就需要用到value值了,比如服務器1,設置了value也就是timeout為當前時間+1秒 ,這個時候服務器2通過get發(fā)現時間已經超過系統(tǒng)當前時間了,那就說明服務器1沒有釋放鎖,服務器1可能出問題了,服務器2就開始執(zhí)行刪除key操作,并且繼續(xù)執(zhí)行setnx操作。

但是這塊有一個問題,也就是不光你服務器2可能會發(fā)現服務器1超時了,服務器3也可能會發(fā)現,如果剛好服務器2 setnx操作完成,服務器3就接著刪除,是不是服務器3也可以setnx成功了?

那就等于是服務器2和服務器3都拿到鎖了,那就問題大了。這個時候怎么辦呢?

這個時候需要用到“GETSET key value”命令了。這個命令的意思就是獲取當前key的值,并且設置新的值。

假設服務器2發(fā)現key過期了,開始調用getset命令,然后用獲取的時間判斷是否過期,如果獲取的時間仍然是過期的,那就說明拿到鎖了。

如果沒有,則說明在服務2執(zhí)行getset之前,服務器3可能也發(fā)現鎖過期了,并且在服務器2之前執(zhí)行了getset操作,重新設置了過期時間。

那么服務器2就需要放棄后續(xù)的操作,繼續(xù)等待服務器3釋放鎖或者去監(jiān)測key的有效期是否過期。

這塊其實有一個小問題是,服務器3已經修改了有效期,拿到鎖之后,服務器2也修改了有效期,但是沒能拿到鎖,但是這個有效期的時間已經被在服務器3的基礎上有增加一些,但是這種影響其實還是很小的,幾乎可以忽略不計。

2、為什么Zookeeper可實現分布式鎖?

ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。那對于我們初次認識的人,可以理解成ZooKeeper就像是我們的電腦文件系統(tǒng),我們可以在d盤中創(chuàng)建文件夾a,并且可以繼續(xù)在文件夾a中創(chuàng)建文件夾a1,a2。

那我們的文件系統(tǒng)有什么特點?那就是同一個目錄下文件名稱不能重復,同樣ZooKeeper也是這樣的。

在ZooKeeper所有的節(jié)點,也就是文件夾稱作Znode,而且這個Znode節(jié)點是可以存儲數據的。我們可以通過“ create /zkjjj nice”來創(chuàng)建一個節(jié)點,這個命令就表示,在跟目錄下創(chuàng)建一個zkjjj的節(jié)點,值是nice。同樣這里的值,和我在前面說的Redis中的一樣,沒什么意義,你隨便給。

另外ZooKeeper可以創(chuàng)建4種類型的節(jié)點,分別是:

  • 持久性節(jié)點
  • 持久性順序節(jié)點
  • 臨時性節(jié)點
  • 臨時性順序節(jié)點

首先說下持久性節(jié)點和臨時性節(jié)點的區(qū)別:

  • 持久性節(jié)點表示只要你創(chuàng)建了這個節(jié)點,那不管你ZooKeeper的客戶端是否斷開連接,ZooKeeper的服務端都會記錄這個節(jié)點;
  • 臨時性節(jié)點剛好相反,一旦你ZooKeeper客戶端斷開了連接,那ZooKeeper服務端就不再保存這個節(jié)點;
  • 順便也說下順序性節(jié)點,順序性節(jié)點是指,在創(chuàng)建節(jié)點的時候,ZooKeeper會自動給節(jié)點編號比如0000001,0000002這種的。

Zookeeper有一個監(jiān)聽機制,客戶端注冊監(jiān)聽它關心的目錄節(jié)點,當目錄節(jié)點發(fā)生變化(數據改變、被刪除、子目錄節(jié)點增加刪除)等,Zookeeper會通知客戶端。

四、在Zookeeper中如何加鎖?

下面我們繼續(xù)結合我們上面的分紅包場景,描述下在Zookeeper中如何加鎖。

假設服務器1,創(chuàng)建了一個節(jié)點 /zkjjj,成功了,那服務器1就獲取了鎖,服務器2再去創(chuàng)建相同的鎖,就會失敗,這個時候就只能監(jiān)聽這個節(jié)點的變化。

等到服務器1處理完業(yè)務,刪除了節(jié)點后,他就會得到通知,然后去創(chuàng)建同樣的節(jié)點,獲取鎖處理業(yè)務,再刪除節(jié)點,后續(xù)的100臺服務器與之類似。

注意這里的100臺服務器并不是挨個去執(zhí)行上面的創(chuàng)建節(jié)點的操作,而是并發(fā)的,當服務器1創(chuàng)建成功,那么剩下的99個就都會注冊監(jiān)聽這個節(jié)點,等通知,以此類推。

但是大家有沒有注意到,這里還是有問題的,還是會有死鎖的情況存在,對不對?

當服務器1創(chuàng)建了節(jié)點后掛了,沒能刪除,那其他99臺服務器就會一直等通知,那就完蛋了。。。

這個時候就需要用到臨時性節(jié)點了,我們前面說過了,臨時性節(jié)點的特點是客戶端一旦斷開,就會丟失,也就是當服務器1創(chuàng)建了節(jié)點后,如果掛了,那這個節(jié)點會自動被刪除,這樣后續(xù)的其他服務器,就可以繼續(xù)去創(chuàng)建節(jié)點,獲取鎖了。

但是我們可能還需要注意到一點,就是驚群效應:舉一個很簡單的例子,當你往一群鴿子中間扔一塊食物,雖然最終只有一個鴿子搶到食物,但所有鴿子都會被驚動來爭奪,沒有搶到…

就是當服務器1節(jié)點有變化,會通知其余的99個服務器,但是最終只有1個服務器會創(chuàng)建成功,這樣98還是需要等待監(jiān)聽,那么為了處理這種情況,就需要用到臨時順序性節(jié)點。大致意思就是,之前是所有99個服務器都監(jiān)聽一個節(jié)點,現在就是每一個服務器監(jiān)聽自己前面的一個節(jié)點。

假設100個服務器同時發(fā)來請求,這個時候會在/zkjjj節(jié)點下創(chuàng)建100個臨時順序性節(jié)點/zkjjj/000000001,/zkjjj/000000002,一直到/zkjjj/000000100,這個編號就等于是已經給他們設置了獲取鎖的先后順序了。

當001節(jié)點處理完畢,刪除節(jié)點后,002收到通知,去獲取鎖,開始執(zhí)行,執(zhí)行完畢,刪除節(jié)點,通知003~以此類推。

分享到:
標簽:分布式
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰(zhàn)2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定