欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis分布式鎖詳細(xì)介紹

 更新時(shí)間:2021年12月06日 11:32:46   作者:-阿布-  
大家好,本篇文章主要講的是Redis分布式鎖詳細(xì)介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽

分布式鎖

在單進(jìn)程應(yīng)用中,當(dāng)一段代碼同一時(shí)間內(nèi)只能由一個(gè)線程執(zhí)行時(shí),

多線程下可能會(huì)出錯(cuò),例如兩個(gè)線程同時(shí)對(duì)一個(gè)數(shù)字做累加,兩個(gè)線程同時(shí)拿到了該數(shù)字,例如40,一個(gè)線程加了10,一個(gè)線程加了20,正確結(jié)果應(yīng)該是70,

但由于兩個(gè)線程在自己的內(nèi)存中一個(gè)算出的是50,一個(gè)算出的是60,此時(shí)二者都將自己的結(jié)果往該數(shù)字原本的地方寫(保存),

這時(shí)候,肯定會(huì)有一個(gè)線程的值會(huì)被覆蓋,因?yàn)樽x取->計(jì)算->保存 并不是原子操作(原子操作是指不會(huì)被線程調(diào)度機(jī)制打斷的操作,這種操作一旦開始,就會(huì)一直運(yùn)行結(jié)束,中間不會(huì)有任何線程切換),

也就是說最終的結(jié)果要么是50,要么是60,而不可能是70(出現(xiàn)并發(fā)或并行的情況下,這種情況大概率會(huì)發(fā)生),

image.png

單進(jìn)程應(yīng)用發(fā)生這種情況時(shí),可以由程序提供的鎖語義直接上鎖(例如java中的sychornized)保證該段代碼只會(huì)被一個(gè)線程執(zhí)行,按照順序來進(jìn)行,結(jié)果將是正確的。

在分布式應(yīng)用中,由于一臺(tái)機(jī)器上可能跑著相同的應(yīng)用進(jìn)程,或者在不同的機(jī)器上跑著,原本程序自帶的語義鎖已經(jīng)無法起到作用,

因?yàn)橄嗤拇a可能是在不同的機(jī)器、進(jìn)程中執(zhí)行,所以此時(shí)需要一個(gè)能夠讓不同機(jī)器、進(jìn)程中,相同的應(yīng)用代碼執(zhí)行到同一段代碼時(shí),也能夠按照順序執(zhí)行(或者同一時(shí)間內(nèi)只有一個(gè)線程能夠執(zhí)行),

這就需要用到中間件來協(xié)調(diào),可以實(shí)現(xiàn)分布式鎖的中間件有很多,redis就是其中一個(gè)。

redis實(shí)現(xiàn)分布式鎖的原理

redis中分布式鎖的原理其實(shí)就是在redis當(dāng)中設(shè)置一個(gè)值(當(dāng)然要保證分布式應(yīng)用連的都是同一個(gè)redis,以這個(gè)redis作為中間點(diǎn),否則當(dāng)然是沒用的),這個(gè)值只能由一個(gè)線程來存放,當(dāng)其他線程(或者不同機(jī)器上的進(jìn)程)也來存放時(shí),發(fā)現(xiàn)這個(gè)值已經(jīng)存在了,就說明此時(shí)已經(jīng)有人在用這把鎖了,這時(shí)候要么進(jìn)行重試等待,要么進(jìn)行放棄。

設(shè)置一般使用 SETNX (set if not exists) 指令,如果該值沒有,則進(jìn)行設(shè)置,有了則不設(shè)置,這就是拿鎖的關(guān)鍵了,當(dāng)拿到鎖的人執(zhí)行處理完畢后,再調(diào)用 DEL 執(zhí)行進(jìn)行鎖的釋放。

死鎖問題

使用 SETNX 和 DEL 實(shí)現(xiàn)了分布式鎖,但是有一種情況,如果一個(gè)線程進(jìn)行了 SETNX 拿到鎖成功后,突然這個(gè)線程因?yàn)槟撤N原因崩潰了,導(dǎo)致沒有進(jìn)行 DEL 釋放鎖,

那么此時(shí),將會(huì)導(dǎo)致其他所有的應(yīng)用都再也沒辦法拿到這把鎖,也就是 死鎖 ,這個(gè)問題的解決方式是將鎖設(shè)置一個(gè)有效期,到了有效期之后該鎖將被自動(dòng)釋放,

使用 EXPIRE 可以給鎖設(shè)置一個(gè)有效期,如下

SETNX LOCK-KEY-NAME true
EXPIRE LOCK-KEY-NAME 5

但是還有一個(gè)問題,因?yàn)?SETNX 和 EXPIRE 是分為兩個(gè)指令執(zhí)行的,這中間依然有可能出現(xiàn) SETNX 執(zhí)行完畢后,由于認(rèn)為或者機(jī)器、程序發(fā)生的故障 導(dǎo)致 EXPIRE 沒有執(zhí)行成功,此時(shí)還是有可能會(huì)發(fā)生死鎖,

image.png

事務(wù)能不能解決這個(gè)問題?

NO,因?yàn)?EXPIRE 是依賴 SETNX 的執(zhí)行結(jié)果執(zhí)行的,只有 SETNX 成功后,才能進(jìn)行 EXPIRE,否則是不可以執(zhí)行的,事務(wù)里并沒有 if else 的分支邏輯,要么全部執(zhí)行,要么一個(gè)都不執(zhí)行。

在 redis2.8 的版本中,引入了set指令的拓展參數(shù),可以讓 SETNX 和 EXPIRE 同時(shí)執(zhí)行(原子),解決了超時(shí)問題,

SET LOCK-KEY-NAME true ex 5 nx

超時(shí)問題

上面雖然說到利用給鎖設(shè)置過期時(shí)間解決可能會(huì)發(fā)生的死鎖問題,但是萬一我的程序代碼執(zhí)行時(shí)間超過了設(shè)置的過期時(shí)間,這時(shí)候鎖自動(dòng)釋放了,但是我的代碼還沒執(zhí)行完畢,其他人又進(jìn)行執(zhí)行了,導(dǎo)致結(jié)果出錯(cuò)怎么辦?

在一般的開發(fā)場景中,我們會(huì)盡量將鎖的時(shí)間設(shè)置的長一些,例如60s,一般應(yīng)用程序在60s內(nèi)都能執(zhí)行完畢,但是怕就怕的是較真,如果60s內(nèi)也執(zhí)行不完怎么辦?

此時(shí)可以使用一種續(xù)期的方案,就是當(dāng)程序在執(zhí)行過程中,不斷的判斷鎖是否快要過期,代碼是否執(zhí)行完畢,如果快過期了沒有執(zhí)行完畢,就將這把鎖進(jìn)行續(xù)期,保證鎖不會(huì)被自動(dòng)釋放,直到我們的代碼執(zhí)行完畢為止,這種方案在java中由一個(gè)叫做 redisson 的框架實(shí)現(xiàn)了,可以直接引入使用。

鎖誤放問題

在鎖的使用過程中,很有可能出現(xiàn)其他應(yīng)用沒有拿到鎖,但是也執(zhí)行了 DEL 指令,將我們正在執(zhí)行中的程序的鎖釋放了,導(dǎo)致其他地方拿到鎖,進(jìn)入代碼段開始執(zhí)行,

這里的解決方式是,在SETNX的時(shí)候,可以將value設(shè)置成一個(gè)隨機(jī)生成并全局唯一的一串?dāng)?shù)字或字符,該線程一直持有字符,在釋放鎖的時(shí)候,將字符與鎖中的字符進(jìn)行比對(duì),如果匹配,則可以進(jìn)行釋放鎖,如果不匹配,說明是其他人誤放,此時(shí)拒絕釋放,

但是判斷字符是否相同與釋放鎖并不是原子操作,redis也并不提供這么一種命令,所以我們考慮使用lua腳本執(zhí)行這幾步操作(redisson也實(shí)現(xiàn)了),

最重要的一點(diǎn)是,程序中使用釋放鎖的入口一定要統(tǒng)一,萬一有的應(yīng)用程序不使用上面所述的方法釋放,直接使用 DEL ,那么上面說的方案就沒用了(筆者為了測(cè)試,直接用DEL釋放過)。

可重入性

可重入性是指線程在持有鎖的情況下,再次請(qǐng)求加鎖,如果一個(gè)鎖支持同一個(gè)線程的多次加鎖,那么這個(gè)鎖就是可重入的,Java中的 ReentrantLock 就是可重入鎖,大致的原理就是每次獲取到鎖后對(duì)一個(gè)數(shù)字進(jìn)行 +1,每次釋放的時(shí)候進(jìn)行 -1,當(dāng)數(shù)字為0時(shí),分布式鎖被釋放,

redis鎖如果要支持可重入性,也需要用上面的方式進(jìn)行支持,不過該邏輯加重了復(fù)雜性,一般推薦將需要鎖的代碼段進(jìn)行邏輯調(diào)整,避免重復(fù)獲取分布式鎖來處理。(當(dāng)然redisson也支持了可重入鎖)

Redlock

上面的方式看起來沒有太多的問題了,但是由于redis本身可能也會(huì)發(fā)生問題,例如在Sentinel集群中,主節(jié)點(diǎn)掛掉,從節(jié)點(diǎn)變成主節(jié)點(diǎn),但是客戶端這時(shí)候是不知道的,

如果客戶端在剛剛掛掉的主節(jié)點(diǎn)上SETNX成功了,但是這把鎖還沒有同步到從節(jié)點(diǎn)中,從節(jié)點(diǎn)這時(shí)候變成了主節(jié)點(diǎn),這時(shí)候新主節(jié)點(diǎn)中沒有這把鎖的信息,

此時(shí)另一個(gè)客戶端來請(qǐng)求這把鎖,直接 SETNX 成功,又導(dǎo)致了兩個(gè)客戶端同時(shí)在執(zhí)行相同的代碼,又出現(xiàn)了不安全性,

image.png

為此業(yè)界提供了叫做 Redlock 的解決方案,原理大致是,提供多臺(tái)redis實(shí)例,這些實(shí)例之間相互獨(dú)立,沒有主從關(guān)系(沒有任何關(guān)系),同其他分布式算法一樣,使用了大多數(shù)機(jī)制,

加鎖時(shí),它會(huì)向過半節(jié)點(diǎn)發(fā)出 set(key, value, nx = True, ex = xxx)指令,只要過半節(jié)點(diǎn)設(shè)置成功,這把鎖就算拿到了,釋放鎖時(shí)向所有節(jié)點(diǎn)發(fā)出 DEL 指令,

Redlock算法(Redisson已支持)需要考慮出錯(cuò)重試,時(shí)鐘漂移等等細(xì)節(jié)問題,同時(shí)Redlock需要向多個(gè)節(jié)點(diǎn)進(jìn)行讀寫,性能將要比單例redis下降,

如果業(yè)務(wù)場景對(duì)錯(cuò)誤的發(fā)生容忍度很低,又可以接受性能稍微有點(diǎn)下降,可以考慮采用Redlock算法。

到此這篇關(guān)于Redis分布式鎖詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Redis分布式鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis 在真實(shí)世界的 5 個(gè)用法

    Redis 在真實(shí)世界的 5 個(gè)用法

    Redis是一個(gè)開源的使用ANSI C語言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API這篇文章主要介紹了Redis 在真實(shí)世界的 5 個(gè)用法,需要的朋友可以參考下
    2018-03-03
  • 一文掌握Redis的三種集群方案(小結(jié))

    一文掌握Redis的三種集群方案(小結(jié))

    這篇文章主要介紹了一文掌握Redis的三種集群方案(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 解決redis在linux上的部署的問題

    解決redis在linux上的部署的問題

    這篇文章主要介紹了redis在linux上的部署,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Centos7下Redis3.2.8最新版本安裝教程

    Centos7下Redis3.2.8最新版本安裝教程

    這篇文章主要為大家詳細(xì)介紹了Centos7下Redis3.2.8最新版本的安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Redis可視化客戶端小結(jié)

    Redis可視化客戶端小結(jié)

    因?yàn)?Redis 官方只提供了命令行版的 Redis 客戶端 redis-cli,以至于我們?cè)谑褂玫臅r(shí)候會(huì)比較麻煩,而且命令行版的客戶端看起來也不夠直觀,下面是我這些年使用過的一些 Redis 可視化客戶端,分享給大家
    2021-06-06
  • redis5.0以上基于密碼認(rèn)證的集群cluster方式

    redis5.0以上基于密碼認(rèn)證的集群cluster方式

    這篇文章主要介紹了redis5.0以上基于密碼認(rèn)證的集群cluster方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 一文帶你深入理解Redis的主從架構(gòu)

    一文帶你深入理解Redis的主從架構(gòu)

    Redis主從架構(gòu)是一種分布式數(shù)據(jù)庫架構(gòu),它包括一個(gè)主節(jié)點(diǎn)(Master)和一個(gè)或多個(gè)從節(jié)點(diǎn)(Slave),主節(jié)點(diǎn)處理所有寫操作,從節(jié)點(diǎn)負(fù)責(zé)復(fù)制主節(jié)點(diǎn)的數(shù)據(jù)并處理讀請(qǐng)求,本文將帶大家深入理解Redis主從架構(gòu),需要的朋友可以參考下
    2023-09-09
  • 如何使用redis中的zset實(shí)現(xiàn)滑動(dòng)窗口限流

    如何使用redis中的zset實(shí)現(xiàn)滑動(dòng)窗口限流

    滑動(dòng)窗口限流是一種常見的流量控制方法,它限制了在一定時(shí)間窗口內(nèi)的請(qǐng)求數(shù)量,下面是使用Redis ZSet實(shí)現(xiàn)滑動(dòng)窗口限流的一個(gè)簡單示例,需要的朋友可以參考下
    2023-09-09
  • Redis刪除過期key策略詳解

    Redis刪除過期key策略詳解

    Redis是一款高性能的開源內(nèi)存數(shù)據(jù)庫,廣泛應(yīng)用于緩存、消息隊(duì)列、實(shí)時(shí)分析等場景,在Redis中,我們經(jīng)常需要?jiǎng)h除過期的key,以釋放內(nèi)存空間并保持?jǐn)?shù)據(jù)的有效性,本文將為您詳細(xì)介紹Redis的過期key刪除策略,幫助您更好地管理和優(yōu)化Redis數(shù)據(jù)庫
    2023-10-10
  • 詳解Redis高效恢復(fù)策略內(nèi)存快照與AOF

    詳解Redis高效恢復(fù)策略內(nèi)存快照與AOF

    這篇文章主要為大家介紹了Redis高效恢復(fù)策略內(nèi)存快照與AOF及對(duì)比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12

最新評(píng)論