最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

談?wù)凴edis分布式鎖的正確實(shí)現(xiàn)方法

 更新時(shí)間:2019年08月13日 09:43:47   作者:Rytia  
這篇文章主要給大家介紹了關(guān)于Redis分布式鎖的正確實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

最近在參加學(xué)校安排的實(shí)訓(xùn)任務(wù),我們小組需完成一套分布式&微服務(wù)跨境電商,雖然這題目看起來有點(diǎn)老套,并且隊(duì)友多是 Java 技術(shù)棧,所以我光榮(被迫)
的成為了一名前端,并順路使用 PHP 的 Swoole 幫助負(fù)責(zé)服務(wù)器端的同學(xué)編寫了幾個(gè)微服務(wù)模塊。在小組成員之間的協(xié)作中,還是出現(xiàn)了不少有趣的火花。

在昨天 review 隊(duì)友代碼的過程中,發(fā)現(xiàn)了我們組分布式鎖的寫法似乎有點(diǎn)問題,實(shí)現(xiàn)代碼如下:

加鎖部分

解鎖部分

主要原理是使用了 redis 的 setnx 去插入一組 key-value,其中 key 要上鎖的標(biāo)識(shí)(在項(xiàng)目中是鎖死用戶 userId),如果上鎖失敗則返回 false。但是根據(jù)二段鎖的思路,仔細(xì)思考會(huì)存在這么一個(gè)有趣的現(xiàn)象:

假設(shè)微服務(wù) A 的某個(gè)請求對 userId = 7 的用戶上鎖,則微服務(wù) A 的這個(gè)請求可以讀取這個(gè)用戶的信息,且可以修改其內(nèi)容 ;其他模塊只能讀取這個(gè)用戶的信息,無法修改其內(nèi)容。
假設(shè)微服務(wù) A 的當(dāng)前請求對 userId = 7 的用戶解鎖,則所有模塊可以讀取這個(gè)用戶的信息,且可以修改其內(nèi)容
如此一來:

  • 若微服務(wù)模塊 A 接收到另一個(gè)需要修改 userId = 7 的用戶 的請求時(shí),假設(shè)這個(gè)用戶還在被鎖狀態(tài)下,這次請求可以修改它嗎?(可以,解個(gè)鎖就行)
  • 若微服務(wù)模塊 B 接收到另一個(gè)需要修改 userId = 7 的用戶 的請求時(shí),假設(shè)這個(gè)用戶還在被鎖狀態(tài)下,這次請求可以修改它嗎?(可以,解個(gè)鎖就行)
  • 若微服務(wù)模塊 A 執(zhí)行上鎖的請求中途意外崩掉,其他用戶還能修改信息嗎? (可以,解個(gè)鎖就行)

很明顯,這三點(diǎn)并不是我們所希望的。那么如何實(shí)現(xiàn)分布式鎖才是最佳實(shí)踐吶?

一個(gè)好的分布式鎖需要實(shí)現(xiàn)什么

  • 由某個(gè)模塊的某次請求上鎖,并且只有由這個(gè)模塊的這次請求解鎖(互斥,只能有一個(gè)微服務(wù)的某次請求持有鎖)
  • 若上鎖模塊的上鎖請求超時(shí)執(zhí)行,則應(yīng)自動(dòng)解鎖,并還原其所做修改(容錯(cuò),就算 一個(gè)持有鎖的微服務(wù)宕機(jī)也不影響最終其他模塊的上鎖 )

我們應(yīng)該怎么做

綜上所述,我們小組的分布式鎖在實(shí)現(xiàn)模塊互斥的情況下,忽略的一個(gè)重要問題便是“請求互斥”。我們只需要在加鎖時(shí),key-value 的值保存為當(dāng)前請求的 requestId ,解鎖時(shí)加多一次判斷,是否為同一請求即可。

那么這么修改之后,我們可以高枕無憂了嗎?

是的,夠用了。因?yàn)槲覀冮_發(fā)環(huán)境 Redis 是統(tǒng)一用一臺(tái)服務(wù)器上的單例,采用上述方式實(shí)現(xiàn)的分布式鎖并沒有什么問題,但在準(zhǔn)備部署到生產(chǎn)環(huán)境下時(shí),突然意識(shí)到一個(gè)問題:如果實(shí)現(xiàn)主從讀寫分離,redis 多機(jī)主從同步數(shù)據(jù)時(shí),采用的是異步復(fù)制,也便是一個(gè)“寫”操作到我們的 reids 主庫之后,便馬上返回成功(并不會(huì)等到同步到從庫后再返回,如果這種是同步完成后再返回便是同步復(fù)制),這將會(huì)造成一個(gè)問題:

假設(shè)我們的模塊 A中 id=1 的請求上鎖成功后,沒同步到從庫前主庫被我們玩壞了(宕機(jī)),則 redis 哨兵將會(huì)從從庫中選擇出一臺(tái)新的主庫,此時(shí)若模塊 A 中 id=2 的請求重新請求加鎖,將會(huì)是成功的。

技不如人,我們只能借助搜索引擎劃水了(大霧),發(fā)現(xiàn)這種情況還真的有通用的解決方案:redlock。

怎么實(shí)現(xiàn) Redlock 分布式安全鎖

首先 redlock 是 redis 官方文檔推薦的實(shí)現(xiàn)方式,本身并沒有用到主從層面的架構(gòu),采用的是多態(tài)主庫,依次去取鎖的方式。假設(shè)這里有 5 臺(tái)主庫,整體流程大致如下:

加鎖

  1. 應(yīng)用層請求加鎖
  2. 依次向 5 臺(tái) redis 服務(wù)器發(fā)送請求
  3. 若有超過半數(shù)的服務(wù)器返回加鎖成功,則完成加鎖,如果沒有則自動(dòng)執(zhí)行解鎖,并等待一段隨機(jī)時(shí)間后重試。(客觀原因加鎖失?。壕W(wǎng)絡(luò)情況不好、服務(wù)器未響應(yīng)等問題, 等待一段隨機(jī)時(shí)間后重試可以避開“蜂擁而進(jìn)”的情況造成服務(wù)器資源占用瞬時(shí)猛增 )
  4. 如有其中任意一臺(tái)服務(wù)器已經(jīng)持有該鎖,則加鎖失敗, 等待一段隨機(jī)時(shí)間后重試。 (主觀原因加鎖失敗:已經(jīng)被被別人鎖上了)

解鎖

直接向 5 臺(tái)服務(wù)器發(fā)起請求即可,無論這臺(tái)服務(wù)器上是不是已經(jīng)有鎖。

整體思路很簡單,但是實(shí)現(xiàn)起來仍有許多值得注意的地方。在向這 5 臺(tái)服務(wù)器發(fā)送加鎖請求時(shí),由于會(huì)帶上一個(gè)過期時(shí)間以保證上文所提到的“自動(dòng)解鎖(容錯(cuò)性) ”,考慮到延時(shí)等原因,這 5 臺(tái)機(jī)自動(dòng)解鎖的時(shí)間不完全相同,因此存在一個(gè)加

鎖時(shí)間差的問題,一般而言是這么解決的:

  • 在加鎖之前,必須在應(yīng)用層(或者把分布式鎖單獨(dú)封裝成一個(gè)全局通用的微服務(wù)亦可)2. 記錄請求加鎖的時(shí)間戳 T1
  • 完成最后一臺(tái) redis 主庫加鎖后,記錄時(shí)間戳 T2
  • 則加鎖所需時(shí)間為 T1 – T2
  • 假設(shè)資源自動(dòng)解鎖的時(shí)間為 10 秒后,則資源真正可利用的時(shí)間為 10 – T1 + T2。若

可利用時(shí)間不符合預(yù)期,或者為負(fù)數(shù),你懂的,重新來一遍吧。

如果你對鎖的過期時(shí)間有著更加嚴(yán)格的把控,可以把 T1 到第一臺(tái)服務(wù)器加鎖成功的時(shí)間單獨(dú)記錄,再在最后的可用時(shí)間上加上這段時(shí)間即可得到一個(gè)更加準(zhǔn)確的值

現(xiàn)在考慮另一個(gè)問題,如果恰好某次請求的鎖保存在了三臺(tái)服務(wù)器上,其中這三臺(tái)都宕機(jī)了(怎么這么倒霉.. TAT),那此時(shí)另一個(gè)請求又來請求加鎖,豈不又回到最初我們小組所面臨的問題了?很遺憾的說,是的,在這種問題上官方文檔給出的答案是:啟用AOF持久化功能情況會(huì)得到好轉(zhuǎn) 🙂

關(guān)于性能方面的處理, 一般而言不止要求低延時(shí),同時(shí)要求高吞吐量,我們可以按照官方文檔的說法, 采用多路傳輸同時(shí)對 5 臺(tái) redis 主庫進(jìn)行通信以降低整體耗時(shí),或者把 socket 設(shè)置成非阻塞模式 (這樣的好處是發(fā)送命令時(shí)并不等待返回,因此可以一次性發(fā)送全部命令再進(jìn)行等待整體運(yùn)行結(jié)果,雖然本人認(rèn)為通常情況下如果本身網(wǎng)絡(luò)延遲極低的情況下作用不大,等待服務(wù)器處理的時(shí)間占比會(huì)更加大)

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Redis服務(wù)器優(yōu)化方式

    Redis服務(wù)器優(yōu)化方式

    文章分享了常見的Redis服務(wù)器優(yōu)化技巧和策略,主要包括內(nèi)存管理、持久化配置、連接配置和網(wǎng)絡(luò)優(yōu)化四個(gè)方面,內(nèi)存管理主要是設(shè)置maxmemory參數(shù)和選擇合適的內(nèi)存淘汰策略,持久化配置包括RDB持久化和AOF持久化
    2024-09-09
  • Redis分布式鎖的超時(shí)問題及解決

    Redis分布式鎖的超時(shí)問題及解決

    這篇文章主要介紹了Redis分布式鎖的超時(shí)問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題解決

    遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題解決

    本文主要介紹了遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題,出現(xiàn)?Redis Client On Error: Error: connect ECONNREFUSED 47.100.XXX.XX:6379?錯(cuò)誤,下面就來介紹一下解決方法,感興趣的可以了解一下
    2025-04-04
  • Redis主從復(fù)制詳解

    Redis主從復(fù)制詳解

    今天小編就為大家分享一篇關(guān)于Redis主從復(fù)制詳解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • redis中隊(duì)列消息實(shí)現(xiàn)應(yīng)用解耦的方法

    redis中隊(duì)列消息實(shí)現(xiàn)應(yīng)用解耦的方法

    這篇文章主要給大家介紹了關(guān)于redis中隊(duì)列消息實(shí)現(xiàn)應(yīng)用解耦的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • Redis搶單預(yù)熱的實(shí)現(xiàn)示例

    Redis搶單預(yù)熱的實(shí)現(xiàn)示例

    本文主要介紹了Redis搶單預(yù)熱的實(shí)現(xiàn)示例,以應(yīng)對搶單活動(dòng)帶來的高并發(fā)訪問壓力,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 淺談Redis變慢的原因及排查方法

    淺談Redis變慢的原因及排查方法

    本文主要介紹了淺談Redis變慢的原因及排查方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 讓Redis在你的系統(tǒng)中發(fā)揮更大作用的幾點(diǎn)建議

    讓Redis在你的系統(tǒng)中發(fā)揮更大作用的幾點(diǎn)建議

    Redis在很多方面與其他數(shù)據(jù)庫解決方案不同:它使用內(nèi)存提供主存儲(chǔ)支持,而僅使用硬盤做持久性的存儲(chǔ);它的數(shù)據(jù)模型非常獨(dú)特,用的是單線程。另一個(gè)大區(qū)別在于,你可以在開發(fā)環(huán)境中使用Redis的功能,但卻不需要轉(zhuǎn)到Redis
    2014-06-06
  • RedisAPI原子性操作及原理解析

    RedisAPI原子性操作及原理解析

    這篇文章主要介紹了RedisAPI原子性操作及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Redis實(shí)現(xiàn)用戶關(guān)注的項(xiàng)目實(shí)踐

    Redis實(shí)現(xiàn)用戶關(guān)注的項(xiàng)目實(shí)踐

    本文主要介紹了Redis實(shí)現(xiàn)用戶關(guān)注的項(xiàng)目實(shí)踐,通過使用Redis的set數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)關(guān)注對象,方便高效地進(jìn)行添加和取消關(guān)注操作,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02

最新評(píng)論

于都县| 清水县| 五指山市| 客服| 大荔县| 彰武县| 林芝县| 博客| 小金县| 柯坪县| 来宾市| 汾阳市| 梧州市| 什邡市| 蓝田县| 临泽县| 孙吴县| 闽清县| 元阳县| 岳普湖县| 建阳市| 延吉市| 宁乡县| 栾川县| 宜阳县| 南昌县| 南靖县| 乌拉特后旗| 信宜市| 兴山县| 南充市| 澄迈县| 三明市| 伊宁市| 康马县| 利津县| 甘孜| 墨竹工卡县| 渝中区| 阿拉善右旗| 平谷区|