<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          《redis in action》Redis分布式鎖

          共 1834字,需瀏覽 4分鐘

           ·

          2021-04-22 22:39

          這塊作者還是大概得將書中的內(nèi)容進(jìn)行一下翻譯,首先為啥要用redis分布式鎖。我們在之前學(xué)redis事務(wù)的時候說redis提供了watch/mutli/exec機(jī)制,其中的watch是樂觀鎖。也就是通過監(jiān)聽某個數(shù)據(jù)的變動來做出相應(yīng)的改變。當(dāng)時我們也說了redis的watch樂觀鎖為啥不像關(guān)系型數(shù)據(jù)庫那樣直接禁止別其他客戶端修改的問題。Redis更多的還是基于其效率設(shè)計,因此通過盡可能快的通知客戶端去維護(hù)數(shù)據(jù)的安全性,通過watch的樂觀鎖和mutli/exec事務(wù)來看。確實可以直接做分布式鎖,為啥可以做這件事的原因是watch命令的監(jiān)聽特性會一直持續(xù)到exec的執(zhí)行,如果watch的鍵值發(fā)生變化,那么watch后邊的事務(wù)是不會執(zhí)行的。但是我們必須要保持我們的事務(wù)不會出現(xiàn)指令性質(zhì)的錯誤,這塊我們之前說過redis事務(wù)本身和關(guān)系型數(shù)據(jù)庫事務(wù)不一樣,執(zhí)行出錯期間不能回滾。
          使用watch去做分布式鎖的過程大概如下,這里直接截書中的python代碼了:
          使用watch做分布式鎖的問題在于效率問題,我們說watch的樂觀鎖為了就是及時通知客戶端,然后讓其發(fā)起重試,所以當(dāng)加鎖壓力比較大的時候重試就非常常見。加之watch/multi/exec的執(zhí)行過程,所以時間消耗非常明顯。書中專門還做了相關(guān)的測試。具體如下:
          我們看到隨著買賣的人員越來越多,單筆交易所發(fā)生的重試次數(shù)不斷提升,而且平均等待時間也不斷增長??紤]到重試代碼反復(fù)運(yùn)行以及重試的網(wǎng)絡(luò)時間消耗以及相關(guān)watch事務(wù)通信,因此我們考慮是否有一種可以直接類似if這樣的條件語句來做這件事,相當(dāng)于將復(fù)雜的過程簡單化。這塊還真有,redis提供了setnx命令,這個命令是什么意思吶?悄悄告訴你,這個命令就是說如果key不存在的時候,我才給這個key設(shè)置一個值?;诖?,我們數(shù)以百計得redis客戶端有救了,各個客戶端只需要這個命令就判斷是否已經(jīng)被加鎖,時候獲取了鎖。我們看下邊的代碼:
          這塊在獲取鎖的時候,設(shè)置一個時間限制。超過這個時間我們就當(dāng)作獲取鎖失敗了,那么咋就發(fā)起重試,但是咋并沒有建立事務(wù)啥的,因為太麻煩了。當(dāng)我們獲取鎖之后我們將我們的鎖的唯一標(biāo)識返回,為啥要返回的原因:方便進(jìn)行鎖釋放,您可能會問直接刪除key不就行了么,咋那么麻煩,這塊您需要考慮多次釋放鎖以及鎖已經(jīng)被其他進(jìn)程獲取,然后當(dāng)前進(jìn)程把其他進(jìn)程的鎖釋放導(dǎo)致其他進(jìn)程業(yè)務(wù)出現(xiàn)錯誤。除此之外我們還要考慮在我們釋放鎖的瞬間,其他進(jìn)程修改了鎖或者破壞了鎖,因為這是不允許的,那會影響我們當(dāng)前的業(yè)務(wù)正常。那么我們就要保證我們釋放鎖得時候這個鎖要是正常的,所以這塊用了上邊我們說的效率比較低的watch樂觀鎖+事務(wù)的鎖機(jī)制。
          通過上述的代碼,書中也做了相關(guān)的測試工作。我們看到通過使用setnx命令做的鎖機(jī)制相對于watch樂觀鎖+事務(wù)的性能提升相當(dāng)?shù)拿黠@,對比太明顯,直接貼圖吧。
          當(dāng)然上述的講述,我們并沒有考慮鎖超時的問題。也就是說當(dāng)前進(jìn)程釋放鎖失敗了,或者直接宕機(jī)等比較嚴(yán)重的問題導(dǎo)致setnx的key沒有被清理。那么其他的進(jìn)程必然無法獲得鎖,必然導(dǎo)致一個老鼠害了一鍋湯的問題。這塊先不討論鎖超時的問題,下次再聊。
          除此之外分布式鎖還有哪些問題?書中總結(jié)了4點:
          第一:一個進(jìn)程獲得鎖,操作了數(shù)據(jù)。但是這個過程花費了太久時間,然后這個鎖考慮到鎖自動超時的問題,被自動釋放了。但是這個進(jìn)程并不知道它已經(jīng)釋放了鎖。所以潛在的問題是這個自動超時時間設(shè)置多大合適吶?是不是一臉問號,總不能寫死吧。
          第二:一個進(jìn)程獲得鎖,然后操作數(shù)據(jù),但是花了太久時間然后宕機(jī)了。其他進(jìn)程想要獲得鎖,但是不知道到底是哪個進(jìn)程一直持有鎖,所以一直傻傻的在哪里等,黃花菜都涼了也沒音信。
          第三:一個進(jìn)程獲得了鎖,但是鎖超時了,其他進(jìn)程獲取了鎖。就這樣這個鎖一直超時,完事導(dǎo)致大量業(yè)務(wù)沒有真正的實現(xiàn)鎖,最終一大批臟數(shù)據(jù)。
          第四:第一和第三個問題組合,導(dǎo)致很多進(jìn)程都堅信自己獲取到了鎖。
          個人感覺這四個問題其實還是一個關(guān)鍵,就是鎖超時時間大小如何動態(tài)修改的問題,如果此問題解決了那么這四個問題就不是問題。

          OK,本次文章就到這里了,天晚了,聽個歌兒吧,晚安!


          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久1AV一二三区 | 日本黄色站视频 | 嫩草成人| 熟女一区| 人人操人人干在线观看 |