久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

用Redis實(shí)現(xiàn)分布式鎖 | Jeff的妙想奇境

 亞典波羅的收藏 2012-07-18

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

Redis有一系列的命令,特點(diǎn)是以NX結(jié)尾,NX是Not eXists的縮寫,,如SETNX命令就應(yīng)該理解為:SET if Not eXists。這系列的命令非常有用,,這里講使用SETNX來(lái)實(shí)現(xiàn)分布式鎖,。

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

利用SETNX非常簡(jiǎn)單地實(shí)現(xiàn)分布式鎖。例如:某客戶端要獲得一個(gè)名字foo的鎖,客戶端使用下面的命令進(jìn)行獲?。?/p>

SETNX lock.foo <current Unix time + lock timeout + 1>

  •  如返回1,,則該客戶端獲得鎖,把lock.foo的鍵值設(shè)置為時(shí)間值表示該鍵已被鎖定,,該客戶端最后可以通過(guò)DEL lock.foo來(lái)釋放該鎖,。
  •  如返回0,表明該鎖已被其他客戶端取得,,這時(shí)我們可以先返回或進(jìn)行重試等對(duì)方完成或等待鎖超時(shí),。

解決死鎖

上面的鎖定邏輯有一個(gè)問(wèn)題:如果一個(gè)持有鎖的客戶端失敗或崩潰了不能釋放鎖,該怎么解決,?我們可以通過(guò)鎖的鍵對(duì)應(yīng)的時(shí)間戳來(lái)判斷這種情況是否發(fā)生了,,如果當(dāng)前的時(shí)間已經(jīng)大于lock.foo的值,說(shuō)明該鎖已失效,,可以被重新使用,。

發(fā)生這種情況時(shí),可不能簡(jiǎn)單的通過(guò)DEL來(lái)刪除鎖,,然后再SETNX一次,,當(dāng)多個(gè)客戶端檢測(cè)到鎖超時(shí)后都會(huì)嘗試去釋放它,這里就可能出現(xiàn)一個(gè)競(jìng)態(tài)條件,讓我們模擬一下這個(gè)場(chǎng)景:

  1.  C0操作超時(shí)了,,但它還持有著鎖,,C1和C2讀取lock.foo檢查時(shí)間戳,先后發(fā)現(xiàn)超時(shí)了,。
  2.  C1 發(fā)送DEL lock.foo
  3.  C1 發(fā)送SETNX lock.foo 并且成功了,。
  4.  C2 發(fā)送DEL lock.foo
  5.  C2 發(fā)送SETNX lock.foo 并且成功了。

這樣一來(lái),,C1,,C2都拿到了鎖!問(wèn)題大了,!

幸好這種問(wèn)題是可以避免D,,讓我們來(lái)看看C3這個(gè)客戶端是怎樣做的:

  1. C3發(fā)送SETNX lock.foo 想要獲得鎖,由于C0還持有鎖,,所以Redis返回給C3一個(gè)0
  2. C3發(fā)送GET lock.foo 以檢查鎖是否超時(shí)了,,如果沒(méi)超時(shí),則等待或重試,。
  3. 反之,,如果已超時(shí),C3通過(guò)下面的操作來(lái)嘗試獲得鎖:
    GETSET lock.foo <current Unix time + lock timeout + 1>
  4. 通過(guò)GETSET,,C3拿到的時(shí)間戳如果仍然是超時(shí)的,,那就說(shuō)明,,C3如愿以償拿到鎖了。
  5. 如果在C3之前,,有個(gè)叫C4的客戶端比C3快一步執(zhí)行了上面的操作,,那么C3拿到的時(shí)間戳是個(gè)未超時(shí)的值,這時(shí),,C3沒(méi)有如期獲得鎖,,需要再次等待或重試。留意一下,,盡管C3沒(méi)拿到鎖,但它改寫了C4設(shè)置的鎖的超時(shí)值,,不過(guò)這一點(diǎn)非常微小的誤差帶來(lái)的影響可以忽略不計(jì),。

注意:為了讓分布式鎖的算法更穩(wěn)鍵些,持有鎖的客戶端在解鎖之前應(yīng)該再檢查一次自己的鎖是否已經(jīng)超時(shí),,再去做DEL操作,,因?yàn)榭赡芸蛻舳艘驗(yàn)槟硞€(gè)耗時(shí)的操作而掛起,操作完的時(shí)候鎖因?yàn)槌瑫r(shí)已經(jīng)被別人獲得,,這時(shí)就不必解鎖了,。

示例偽代碼

根據(jù)上面的代碼,我寫了一小段Fake代碼來(lái)描述使用分布式鎖的全過(guò)程:

  1. # get lock
  2. lock = 0
  3. while lock != 1:
  4.     timestamp = current Unix time + lock timeout + 1
  5.     lock = SETNX lock.foo timestamp
  6.     if lock == 1 or (now() > (GET lock.foo) and now() > (GETSET lock.foo timestamp)):
  7.         break;
  8.     else:
  9.         sleep(10ms)
  10.  
  11. # do your job
  12. do_job()
  13.  
  14. # release
  15. if now() < GET lock.foo:
  16.     DEL lock.foo

是的,,要想這段邏輯可以重用,,使用python的你馬上就想到了Decorator,而用Java的你是不是也想到了那誰(shuí),?AOP + annotation,?行,怎樣舒服怎樣用吧,,別重復(fù)代碼就行,。

1
This entry was posted in 技術(shù) and tagged , , , . Bookmark the permalink.

12 Responses to 用Redis實(shí)現(xiàn)分布式鎖

  1. Zoom.Quiet says:

    這樣只能作同一主機(jī)的不同進(jìn)程/線程的鎖吧?
    Redis 自個(gè)兒不是分布式的哪,這怎么分布式鎖呢?

    • jeff says:

      我所定義的分布式鎖是指支持分布式應(yīng)用(多個(gè)進(jìn)程,多個(gè)主機(jī))共享的鎖,。而不是說(shuō)鎖本身是分布式的,。
      鎖本身若是分布式,那它的可靠性也就值得商榷了,。,。

      我使用Redis這個(gè)機(jī)制實(shí)現(xiàn)鎖,就是為了可以讓程序可以實(shí)現(xiàn)分布式部署啊,。

    • jeff says:

      我理解的分布式鎖中的鎖是指存在應(yīng)用進(jìn)程外的鎖,,傳統(tǒng)的鎖是虛擬機(jī)(或進(jìn)程)級(jí)別的鎖,是活在某個(gè)進(jìn)程內(nèi)的,,使用虛擬機(jī)級(jí)別的鎖的程序是沒(méi)辦法或很難大規(guī)?;蛯?shí)現(xiàn)分布式部署的,。

      如有理解不當(dāng),懇請(qǐng)大媽指正啊,。

      • Sparkle says:

        jeff的思路是對(duì)的,,分布式鎖是指使用鎖的程序是分布的,一般來(lái)說(shuō)是多個(gè)不同的進(jìn)程,,而不是說(shuō)鎖的實(shí)現(xiàn)容器redis本身的實(shí)現(xiàn)是不是分布(集群)

  2. Sparkle says:

    為什么不用expire來(lái)實(shí)現(xiàn)超時(shí),?

    • jeff says:

      expire只能讓Key失效,如果有新的進(jìn)程在Key過(guò)期后拿到了新的鎖,,原來(lái)超時(shí)的進(jìn)程回來(lái)如果不經(jīng)判斷會(huì)誤認(rèn)為那是他持有的鎖,,會(huì)將鎖誤刪了。

      • hoterran says:

        隨機(jī)數(shù)和watch可以解決這個(gè)問(wèn)題
        ————-
        random_key = getrandomkey()
        value = redis.setnx(key, random_key)
        if value == 1:
        redis.expire(key, timeout)
        do_job()
        redis.watch(mykey)
        value = redis.get(mykey)
        if random_key == value:
        redis.multi()
        redis.del(mykey)
        redis.exec
        else:
        #不是自己的鎖,,所以不能刪除
        else:
        #沒(méi)拿到鎖

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多