日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis分布式锁奥义

發布時間:2023/12/4 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis分布式锁奥义 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

分布式鎖

  • 分布式系統進行邏輯處理的時候,經常會遇到并發問題,例如直播場景中,用戶需要連麥主播,當多個用戶在同一個時刻一起連麥時候,應該保證只有一個用戶能連麥成功,我們改怎么保證這種業務場景下保證數據的正確性。
  • 當我們連麥的時候,其實設計到兩個步驟操作,首先讀取房間座位信息,當發現座位沒有被占用,修改作為狀態,之后存儲。但是這幾個步驟并非原子操作,也就是可能存在兩個線程同時讀取,一起修改,這樣肯定會造成數據錯亂。怎樣來保證讀取,修改,存儲,這三個步驟的原子操作就是分布式鎖需要解決的問題。

分布式鎖的奧義

  • 分布式鎖本質上實現就是在Redis中占用一個key值,當別的進程也要來占用這個key時候,發現已經存在這個key,就只能放棄,或者等待key消失。我們一般使用setnx(set if not exists) 命令,只允許被一個客戶占用,先到先得,在用del刪除key,釋放key占用給別的線程
  • 存在的問題,比如邏輯執行期間,出現異常,導致del指令無法執行,占用會陷入死鎖,永遠不能得到釋放,這個問題可以通過過期時間解決,我們在設置key時候添加一個過期時間,這樣中介出現異常,5s后也會自動釋放如下:
新docker-redis:0>setnx lock 3 "1" 新docker-redis:0>expire lock 5 "1"
  • 新的問題, setnx 與expire兩個指令并非原子操作,在兩個指令執行間隔期間掛機,那么還是會死鎖。如果可以一起執行就不會出現這種問題,可能Redis事務來解決問題,但是這種業務場景下不下,因為expire必須在前面setnx成功的前提條件才能夠執行,當setnx沒有獲取鎖,expire是不能執行的,此時同一個事務中這兩個命令會出現一個成功一個失敗,與預期不符合。
  • 為解決此問題,Redis2.8 版本后引入了一個新的指令,是的setnx和expire指令能一起執行,徹底解決分布式鎖的問題,從此后,所有第三方鎖都可以舍棄了,如下:
新docker-redis:0>set lock true ex 5 nx "OK" 新docker-redis:0>set lock true ex 5 nx null
  • 以上指令setnx和expire的組合一起的原子指令,他就是分布式鎖解決的奧義。

還有超時問題

  • Redis分布式鎖還是解決不了某種超時,比如,我設置5s,但是業務太垃圾了執行了6秒,以至于超過了鎖的限制,那么問題出現了。鎖以釋放,剩余邏輯無法得到保護,第二個線程重新持有鎖,然后第一個還沒執行完的線程現在執行完了,給你吧key刪了,這樣是不是很刺激。
  • 為避免這個問題,Redis分布式鎖不要用著長時間的任務,如果偶爾出現問題,造成的數據小錯誤就人肉解決吧。
  • 另外還有一個小的技巧來規避這種刪除問題,我們利用value造一個樂觀鎖,我們在set value的時候設置本輪次邏輯的一個特殊的value值,當我們執行完邏輯后,在刪除之前先確認一下value是否本輪次的value,如果不是表示非本輪次,不執行刪除,如果是當前value,則刪除。
  • 問題又來了,匹配value,刪除key,又不是原子操作,Redis也沒有類似的delifequals的指令,但是Redis4.0 后提供了lua腳本的支持,因為lua腳本可以保證連續多個指令的原子性執行
  • 這并非完美解決方案,還是有部分邏輯在裸奔,那么我們盡量規避吧,還有就是這么長邏輯,應該想到的是優化。
Redis分布式鎖失效情況
  • 在Redis集群中,我們分布式鎖是有一定缺陷的,例如在哨兵模式集群中,主節點掛掉,從節點會取而代之,這對客戶端是無感知的,比如,客戶端A主節點上申請lock,但是這把鎖還沒同步到Slave節點,主節點掛掉,之后從節點變主節點,B客戶端在申請lock,同樣成功,這樣就存在兩把鎖,違背了分布式鎖的初衷。不安全性由此產生。
  • 以上情況在理論上是完全有可能發生的,但是也僅僅只是在主從發生failover的情況下才產生,而且持續時間比較短,業務系統多試情況下是可以容忍的。所以我嗎業務中一般會忽略這種極端的情況。
Redlock算法
  • 遇到問題,解決問題,以上出現的極端情況也是有解決方案的,她流產比較復雜,但是有很多開源的libray已經做了良好的封裝,用戶之間用即可,例如Python中redlock-py
import redlock addres=[{"host":"localhost","port":6789,"db":0 },{"host":"localhost","port":6789,"db":0 },{"host":"localhost","port":6789,"db":0 }] dlm = redlock.Redlock(addrs) success = dlm.lock("lock-liaojiamin", 5000) if success:print 'lock success'dlm.unlock('lock-liaojiamin') else:print 'ock failed'
  • 為了使用Redlock,需要提供多個Redis實例,這些實例之間相互獨立,沒有主從關系。通很多分布式算法一樣,Redlock用大多數機制。
    • 加鎖時候向過半節點發送set(key, value, nx=True, ex=xxx)指令,只要過半節點set成功,就認為加鎖成功
    • 釋放鎖需要想所有節點發送del指令
    • Redlock需要想多個節點進行讀寫,意味著相比單實例Redis的性能會下降。
Redlock使用場景
  • 業務室對高可用性有苛刻的要求,希望一臺Redis掛了也完全不受影響,就應該考慮用Redlock
  • 代價是需要更多的Redis實例,性能也下降,代碼刪還需引入額外的library,運維上也需要特殊對待,這些都是成本。

上一篇:Redis流量控制策略
下一篇:LBS解決方案

總結

以上是生活随笔為你收集整理的Redis分布式锁奥义的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。