這篇文章將為大家詳細講解有關如何使用Redis實現分布式鎖,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
創(chuàng)新互聯(lián)建站是一家專注于網站設計、成都網站制作與策劃設計,武昌網站建設哪家好?創(chuàng)新互聯(lián)建站做網站,專注于網站建設10年,網設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:武昌等地區(qū)。武昌做網站價格咨詢:13518219792加鎖部分
解鎖部分
主要原理是使用了 redis 的 setnx 去插入一組 key-value,其中 key 要上鎖的標識(在項目中是鎖死用戶 userId),如果上鎖失敗則返回 false。但是根據二段鎖的思路,仔細思考會存在這么一個有趣的現象:
假設微服務 A 的某個請求對 userId = 7 的用戶上鎖,則微服務 A 的這個請求可以讀取這個用戶的信息,且可以修改其內容 ;其他模塊只能讀取這個用戶的信息,無法修改其內容。
假設微服務 A 的當前請求對 userId = 7 的用戶解鎖,則所有模塊可以讀取這個用戶的信息,且可以修改其內容
如此一來:
若微服務模塊 A 接收到另一個需要修改 userId = 7 的用戶 的請求時,假設這個用戶還在被鎖狀態(tài)下,這次請求可以修改它嗎?(可以,解個鎖就行)
若微服務模塊 B 接收到另一個需要修改 userId = 7 的用戶 的請求時,假設這個用戶還在被鎖狀態(tài)下,這次請求可以修改它嗎?(可以,解個鎖就行)
若微服務模塊 A 執(zhí)行上鎖的請求中途意外崩掉,其他用戶還能修改信息嗎? (可以,解個鎖就行)
很明顯,這三點并不是我們所希望的。那么如何實現分布式鎖才是最佳實踐吶?
一個好的分布式鎖需要實現什么
由某個模塊的某次請求上鎖,并且只有由這個模塊的這次請求解鎖(互斥,只能有一個微服務的某次請求持有鎖)
若上鎖模塊的上鎖請求超時執(zhí)行,則應自動解鎖,并還原其所做修改(容錯,就算 一個持有鎖的微服務宕機也不影響最終其他模塊的上鎖 )
我們應該怎么做
綜上所述,我們小組的分布式鎖在實現模塊互斥的情況下,忽略的一個重要問題便是“請求互斥”。我們只需要在加鎖時,key-value 的值保存為當前請求的 requestId ,解鎖時加多一次判斷,是否為同一請求即可。
那么這么修改之后,我們可以高枕無憂了嗎?
是的,夠用了。因為我們開發(fā)環(huán)境 Redis 是統(tǒng)一用一臺服務器上的單例,采用上述方式實現的分布式鎖并沒有什么問題,但在準備部署到生產環(huán)境下時,突然意識到一個問題:如果實現主從讀寫分離,redis 多機主從同步數據時,采用的是異步復制,也便是一個“寫”操作到我們的 reids 主庫之后,便馬上返回成功(并不會等到同步到從庫后再返回,如果這種是同步完成后再返回便是同步復制),這將會造成一個問題:
假設我們的模塊 A中 id=1 的請求上鎖成功后,沒同步到從庫前主庫被我們玩壞了(宕機),則 redis 哨兵將會從從庫中選擇出一臺新的主庫,此時若模塊 A 中 id=2 的請求重新請求加鎖,將會是成功的。
技不如人,我們只能借助搜索引擎劃水了(大霧),發(fā)現這種情況還真的有通用的解決方案:redlock。
怎么實現 Redlock 分布式安全鎖
首先 redlock 是 redis 官方文檔推薦的實現方式,本身并沒有用到主從層面的架構,采用的是多態(tài)主庫,依次去取鎖的方式。假設這里有 5 臺主庫,整體流程大致如下:
加鎖
應用層請求加鎖
依次向 5 臺 redis 服務器發(fā)送請求
若有超過半數的服務器返回加鎖成功,則完成加鎖,如果沒有則自動執(zhí)行解鎖,并等待一段隨機時間后重試。(客觀原因加鎖失?。壕W絡情況不好、服務器未響應等問題, 等待一段隨機時間后重試可以避開“蜂擁而進”的情況造成服務器資源占用瞬時猛增 )
如有其中任意一臺服務器已經持有該鎖,則加鎖失敗, 等待一段隨機時間后重試。 (主觀原因加鎖失敗:已經被被別人鎖上了)
解鎖
直接向 5 臺服務器發(fā)起請求即可,無論這臺服務器上是不是已經有鎖。
整體思路很簡單,但是實現起來仍有許多值得注意的地方。在向這 5 臺服務器發(fā)送加鎖請求時,由于會帶上一個過期時間以保證上文所提到的“自動解鎖(容錯性) ”,考慮到延時等原因,這 5 臺機自動解鎖的時間不完全相同,因此存在一個加
鎖時間差的問題,一般而言是這么解決的:
在加鎖之前,必須在應用層(或者把分布式鎖單獨封裝成一個全局通用的微服務亦可)2. 記錄請求加鎖的時間戳 T1
完成最后一臺 redis 主庫加鎖后,記錄時間戳 T2
則加鎖所需時間為 T1 – T2
假設資源自動解鎖的時間為 10 秒后,則資源真正可利用的時間為 10 – T1 + T2。若
可利用時間不符合預期,或者為負數,你懂的,重新來一遍吧。
如果你對鎖的過期時間有著更加嚴格的把控,可以把 T1 到第一臺服務器加鎖成功的時間單獨記錄,再在最后的可用時間上加上這段時間即可得到一個更加準確的值
現在考慮另一個問題,如果恰好某次請求的鎖保存在了三臺服務器上,其中這三臺都宕機了(怎么這么倒霉.. TAT),那此時另一個請求又來請求加鎖,豈不又回到最初我們小組所面臨的問題了?很遺憾的說,是的,在這種問題上官方文檔給出的答案是:啟用AOF持久化功能情況會得到好轉 ?
關于性能方面的處理, 一般而言不止要求低延時,同時要求高吞吐量,我們可以按照官方文檔的說法, 采用多路傳輸同時對 5 臺 redis 主庫進行通信以降低整體耗時,或者把 socket 設置成非阻塞模式 (這樣的好處是發(fā)送命令時并不等待返回,因此可以一次性發(fā)送全部命令再進行等待整體運行結果,雖然本人認為通常情況下如果本身網絡延遲極低的情況下作用不大,等待服務器處理的時間占比會更加大)
關于如何使用Redis實現分布式鎖就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
本文標題:如何使用Redis實現分布式鎖-創(chuàng)新互聯(lián)
網站URL:http://jinyejixie.com/article38/jjcsp.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供關鍵詞優(yōu)化、手機網站建設、外貿建站、靜態(tài)網站、網頁設計公司、網站收錄
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內容