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

歡迎訪問 生活随笔!

生活随笔

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

数据库

getset原子性 redis_Redis 分布式锁进化史解读 + 缺陷分析

發布時間:2024/9/19 数据库 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 getset原子性 redis_Redis 分布式锁进化史解读 + 缺陷分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(給數據分析與開發加星標,提升數據技能)

來源:張佳

tech.dianwoda.com/2018/04/11/redisfen-bu-shi-suo-jin-hua-shi/

Redis分布式鎖進化史

近兩年來微服務變得越來越熱門,越來越多的應用部署在分布式環境中,在分布式環境中,數據一致性是一直以來需要關注并且去解決的問題,分布式鎖也就成為了一種廣泛使用的技術,常用的分布式實現方式為Redis,Zookeeper,其中基于Redis的分布式鎖的使用更加廣泛。

但是在工作和網絡上看到過各個版本的Redis分布式鎖實現,每種實現都有一些不嚴謹的地方,甚至有可能是錯誤的實現,包括在代碼中,如果不能正確的使用分布式鎖,可能造成嚴重的生產環境故障,本文主要對目前遇到的各種分布式鎖以及其缺陷做了一個整理,并對如何選擇合適的Redis分布式鎖給出建議。

各個版本的Redis分布式鎖

V1.0

tryLock(){??
????SETNX?Key?1
????EXPIRE?Key?Seconds
}
release(){??
??DELETE?Key
}

這個版本應該是最簡單的版本,也是出現頻率很高的一個版本,首先給鎖加一個過期時間操作是為了避免應用在服務重啟或者異常導致鎖無法釋放后,不會出現鎖一直無法被釋放的情況。

這個方案的一個問題在于每次提交一個Redis請求,如果執行完第一條命令后應用異常或者重啟,鎖將無法過期,一種改善方案就是使用Lua腳本(包含SETNX和EXPIRE兩條命令),但是如果Redis僅執行了一條命令后crash或者發生主從切換,依然會出現鎖沒有過期時間,最終導致無法釋放。

另外一個問題在于,很多同學在釋放分布式鎖的過程中,無論鎖是否獲取成功,都在finally中釋放鎖,這樣是一個鎖的錯誤使用,這個問題將在后續的V3.0版本中解決。

針對鎖無法釋放問題的一個解決方案基于GETSET命令來實現

V1.1 基于GETSET

tryLock(){??
????NewExpireTime=CurrentTimestamp+ExpireSeconds
????if(SETNX?Key?NewExpireTime?Seconds){
?????????oldExpireTime?=?GET(Key)
??????????if(?oldExpireTime???????????????NewExpireTime=CurrentTimestamp+ExpireSeconds
??????????????CurrentExpireTime=GETSET(Key,NewExpireTime)
??????????????if(CurrentExpireTime?==?oldExpireTime){
????????????????return?1;
??????????????}else{
????????????????return?0;
??????????????}
??????????}
????}
}
release(){??
????????DELETE?key
????}

思路:

1、SETNX(Key,ExpireTime)獲取鎖

2、如果獲取鎖失敗,通過GET(Key)返回的時間戳檢查鎖是否已經過期

3、GETSET(Key,ExpireTime)修改Value為NewExpireTime

4、檢查GETSET返回的舊值,如果等于GET返回的值,則認為獲取鎖成功

注意:這個版本去掉了EXPIRE命令,改為通過Value時間戳值來判斷過期

問題:

1、在鎖競爭較高的情況下,會出現Value不斷被覆蓋,但是沒有一個Client獲取到鎖

2、在獲取鎖的過程中不斷的修改原有鎖的數據,設想一種場景C1,C2競爭鎖,C1獲取到了鎖,C2鎖執行了GETSET操作修改了C1鎖的過期時間,如果C1沒有正確釋放鎖,鎖的過期時間被延長,其它Client需要等待更久的時間

V2.0 基于SETNX

tryLock(){??
????SETNX?Key?1?Seconds
}
release(){??
??DELETE?Key
}

Redis 2.6.12版本后SETNX增加過期時間參數,這樣就解決了兩條命令無法保證原子性的問題。但是設想下面一個場景:

1、C1成功獲取到了鎖,之后C1因為GC進入等待或者未知原因導致任務執行過長,最后在鎖失效前C1沒有主動釋放鎖

2、C2在C1的鎖超時后獲取到鎖,并且開始執行,這個時候C1和C2都同時在執行,會因重復執行造成數據不一致等未知情況

3、C1如果先執行完畢,則會釋放C2的鎖,此時可能導致另外一個C3進程獲取到了鎖

大致的流程圖

存在問題:

1、由于C1的停頓導致C1 和C2同都獲得了鎖并且同時在執行,在業務實現間接要求必須保證冪等性

2、C1釋放了不屬于C1的鎖

V3.0

tryLock(){??
????SETNX?Key?UnixTimestamp?Seconds
}
release(){??
????EVAL(
??????//LuaScript
??????if?redis.call("get",KEYS[1])?==?ARGV[1]?then
??????????return?redis.call("del",KEYS[1])
??????else
??????????return?0
??????end
????)
}

這個方案通過指定Value為時間戳,并在釋放鎖的時候檢查鎖的Value是否為獲取鎖的Value,避免了V2.0版本中提到的C1釋放了C2持有的鎖的問題;另外在釋放鎖的時候因為涉及到多個Redis操作,并且考慮到Check And Set 模型的并發問題,所以使用Lua腳本來避免并發問題。

存在問題:

  • 如果在并發極高的場景下,比如搶紅包場景,可能存在UnixTimestamp重復問題,另外由于不能保證分布式環境下的物理時鐘一致性,也可能存在UnixTimestamp重復問題,只不過極少情況下會遇到。

V3.1

tryLock(){??
????SET?Key?UniqId?Seconds
}
release(){??
????EVAL(
??????//LuaScript
??????if?redis.call("get",KEYS[1])?==?ARGV[1]?then
??????????return?redis.call("del",KEYS[1])
??????else
??????????return?0
??????end
????)
}

Redis 2.6.12后SET同樣提供了一個NX參數,等同于SETNX命令,官方文檔上提醒后面的版本有可能去掉SETNX, SETEX, PSETEX,并用SET命令代替,另外一個優化是使用一個自增的唯一UniqId代替時間戳來規避V3.0提到的時鐘問題。

這個方案是目前最優的分布式鎖方案,但是如果在Redis集群環境下依然存在問題:

由于Redis集群數據同步為異步,假設在Master節點獲取到鎖后未完成數據同步情況下Master節點crash,此時在新的Master節點依然可以獲取鎖,所以多個Client同時獲取到了鎖

分布式Redis鎖:Redlock

V3.1的版本僅在單實例的場景下是安全的,針對如何實現分布式Redis的鎖,國外的分布式專家有過激烈的討論, antirez提出了分布式鎖算法Redlock,在distlock話題下可以看到對Redlock的詳細說明,下面是Redlock算法的一個中文說明(引用)

假設有N個獨立的Redis節點

  • 獲取當前時間(毫秒數)。

  • 按順序依次向N個Redis節點執行獲取鎖的操作。這個獲取操作跟前面基于單Redis節點的獲取鎖的過程相同,包含隨機字符串myrandomvalue,也包含過期時間(比如PX 30000,即鎖的有效時間)。為了保證在某個Redis節點不可用的時候算法能夠繼續運行,這個獲取鎖的操作還有一個超時時間(time out),它要遠小于鎖的有效時間(幾十毫秒量級)。客戶端在向某個Redis節點獲取鎖失敗以后,應該立即嘗試下一個Redis節點。這里的失敗,應該包含任何類型的失敗,比如該Redis節點不可用,或者該Redis節點上的鎖已經被其它客戶端持有(注:Redlock原文中這里只提到了Redis節點不可用的情況,但也應該包含其它的失敗情況)。

  • 計算整個獲取鎖的過程總共消耗了多長時間,計算方法是用當前時間減去第1步記錄的時間。如果客戶端從大多數Redis節點(>= N/2+1)成功獲取到了鎖,并且獲取鎖總共消耗的時間沒有超過鎖的有效時間(lock validity time),那么這時客戶端才認為最終獲取鎖成功;否則,認為最終獲取鎖失敗。

  • 如果最終獲取鎖成功了,那么這個鎖的有效時間應該重新計算,它等于最初的鎖的有效時間減去第3步計算出來的獲取鎖消耗的時間。

  • 如果最終獲取鎖失敗了(可能由于獲取到鎖的Redis節點個數少于N/2+1,或者整個獲取鎖的過程消耗的時間超過了鎖的最初有效時間),那么客戶端應該立即向所有Redis節點發起釋放鎖的操作(即前面介紹的Redis Lua腳本)。

  • 釋放鎖:對所有的Redis節點發起釋放鎖操作

然而Martin Kleppmann針對這個算法提出了質疑,提出應該基于fencing token機制(每次對資源進行操作都需要進行token驗證)

1、Redlock在系統模型上尤其是在分布式時鐘一致性問題上提出了假設,實際場景下存在時鐘不一致和時鐘跳躍問題,而Redlock恰恰是基于timing的分布式鎖

2、另外Redlock由于是基于自動過期機制,依然沒有解決長時間的gc pause等問題帶來的鎖自動失效,從而帶來的安全性問題。 接著antirez又回復了Martin Kleppmann的質疑,給出了過期機制的合理性,以及實際場景中如果出現停頓問題導致多個Client同時訪問資源的情況下如何處理。

針對Redlock的問題,基于Redis的分布式鎖到底安全嗎給出了詳細的中文說明,并對Redlock算法存在的問題提出了分析。

總結

不論是基于SETNX版本的Redis單實例分布式鎖,還是Redlock分布式鎖,都是為了保證下特性

1、安全性:在同一時間不允許多個Client同時持有鎖

2、活性 死鎖:鎖最終應該能夠被釋放,即使Client端crash或者出現網絡分區(通常基于超時機制) 容錯性:只要超過半數Redis節點可用,鎖都能被正確獲取和釋放 所以在開發或者使用分布式鎖的過程中要保證安全性和活性,避免出現不可預測的結果。

另外每個版本的分布式鎖都存在一些問題,在鎖的使用上要針對鎖的實用場景選擇合適的鎖,通常情況下鎖的使用場景包括:

Efficiency(效率):只需要一個Client來完成操作,不需要重復執行,這是一個對寬松的分布式鎖,只需要保證鎖的活性即可;

Correctness(正確性):多個Client保證嚴格的互斥性,不允許出現同時持有鎖或者對同時操作同一資源,這種場景下需要在鎖的選擇和使用上更加嚴格,同時在業務代碼上盡量做到冪等

在Redis分布式鎖的實現上還有很多問題等待解決,我們需要認識到這些問題并清楚如何正確實現一個Redis 分布式鎖,然后在工作中合理的選擇和正確的使用分布式鎖。

推薦閱讀

(點擊標題可跳轉閱讀)

一文弄懂“分布式鎖”

架構師帶你玩轉分布式鎖

Redis 分布式鎖:樂觀鎖的實現

看完本文有收獲?請轉發分享給更多人

關注「數據分析與開發」加星標,提升數據技能

喜歡就點一下「好看」唄~

總結

以上是生活随笔為你收集整理的getset原子性 redis_Redis 分布式锁进化史解读 + 缺陷分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲免费色 | 91全免费| 中文在线√天堂 | 亚洲男人天堂2017 | 日韩有码专区 | 久久视频在线 | 三上悠亚人妻中文字幕在线 | 中文字幕日本一区 | 性感美女在线 | 91免费小视频 | 亚洲aaa| 日本国产在线 | 中国一级特黄录像播放 | 欧美亚洲色综久久精品国产 | 最新的黄色网址 | 色无五月| 开心激情播播网 | 久久色视频 | 伊人激情影院 | 婷婷丁香视频 | 人人妻人人藻人人爽欧美一区 | 欧美11一13sex性hd| 69视频在线| 免费看的黄网站 | 6080一级片| 精品国产一区二区视频 | 麻豆传媒在线免费 | 欧美有码在线观看 | 网站av| 无码人妻精品一区二区三区9厂 | 亚洲黄色在线 | 免费福利在线观看 | 69av国产| 外国电影免费观看高清完整版 | 欧美另类亚洲 | 美女网站免费 | 国产激情自拍 | 久久久69 | 国产成人精品一区二 | 国产精品色呦呦 | 狠狠干狠狠操视频 | 成人久久精品人妻一区二区三区 | 精品一区二区在线播放 | 久久看片 | av中文字幕一区 | 国产系列在线 | 日韩久久一区二区 | 日本黄区免费视频观看 | 久久久18禁一区二区三区精品 | 日韩av一级 | 精品三级av | 欧美天天视频 | av激情久久 | 91香蕉视频黄 | 69欧美视频 | 欧美性一级片 | 黄色片网战 | 天天天天天天天干 | 91禁在线动漫 | 天天操天天看 | 精品少妇爆乳无码av无码专区 | 日韩精品中文字幕在线播放 | 日本一级免费视频 | 亚洲精品在线观看网站 | 欧美人与性动交ccoo | 日日干夜夜干 | www.男人天堂.com | 中文字幕视频免费 | 自拍偷拍亚洲欧美 | 天天搞夜夜爽 | 国产伦精品一区二区三区视频我 | 日韩欧美成人一区二区三区 | 国产欧美一区二区三区沐欲 | 色噜噜在线播放 | 天天干天天色综合 | 久久久久久久久久久影院 | 中文字幕黄色av | 国产99精品视频 | 成人羞羞国产免费游戏 | 精品人妻无码一区二区三区蜜桃一 | 中国二级毛片 | 一及黄色大片 | 精品一区二区不卡 | 欧美日韩亚洲综合 | 国产亚洲福利 | 国产91看片 | 亚洲精品视频一区二区 | 紧身裙女教师三上悠亚红杏 | a中文在线| 国产aⅴ无码片毛片一级一区2 | 日本精品99 | 三级网站免费观看 | 蜜臀久久精品久久久久久酒店 | 亚洲乱码国产乱码精品精的特点 | 亚洲激情欧美 | av解说在线| 欧美挤奶吃奶水xxxxx | 成人午夜久久 | 国产草草影院 |