如何用 Redis 實現分散式鎖
導讀 | Redis 本身可以被多個客戶端共享訪問,正好就是一個共享儲存系統,可以用來儲存分散式鎖,而且 Redis 的讀寫效能高,可以應對高併發的鎖操作場景。 |
今天跟大家聊聊兩個問題:
- 如何用 Redis 實現分散式鎖?
- Redis 是如何解決叢集情況下分散式鎖的可靠性問題的?
- 如果 key 不存在,則顯示插入成功,可以用來表示加鎖成功;
- 如果 key 存在,則會顯示插入失敗,可以用來表示加鎖失敗。
- 基於 Redis 節點實現分散式鎖時,對於加鎖操作,我們需要滿足三個條件。
- 加鎖包括了讀取鎖變數、檢查鎖變數值和設定鎖變數值三個操作,但需要以原子操作的方式完成,所以,我們使用 SET 帶上 NX 選項來實現加鎖;
- 鎖變數需要設定過期時間,以免客戶端拿到鎖後發生異常,導致鎖一直無法釋放,所以,我們在 SET 命令執行時加上 EX/PX 選項,設定其過期時間;
- 鎖變數的值需要能區分來自不同客戶端的加鎖操作,以免在釋放鎖時,出現誤釋放操作,所以,我們使用 SET 命令設定鎖變數值時,每個客戶端設定的值是一個唯一值,用於標識客戶端;
分散式鎖是用於分散式環境下併發控制的一種機制,用於控制某個資源在同一時刻只能被一個應用所使用。如下圖所示:
Redis 本身可以被多個客戶端共享訪問,正好就是一個共享儲存系統,可以用來儲存分散式鎖,而且 Redis 的讀寫效能高,可以應對高併發的鎖操作場景。
Redis 的 SET 有個 NX 引數可以實現「key不存在才插入」,所以可以用它來實現分散式鎖:
滿足這三個條件的分散式命令如下:
SET lock_key unique_value NX PX 10000
而解鎖的過程就是將 lock_key 鍵刪除(del lock_key),但不能亂刪,要保證執行操作的客戶端就是加鎖的客戶端。所以,解鎖的時候,我們要先判斷鎖的 unique_value 是否為加鎖客戶端,是的話,才將 lock_key 鍵刪除。
可以看到,解鎖是有兩個操作,這時就需要 Lua 來保證解鎖的原子性,因為 Redis 在執行 Lua 時,可以以原子性的方式執行,保證了鎖釋放操作的原子性。
// 釋放鎖時,先比較 unique_value 是否相等,避免鎖的誤釋放 if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
這樣一來,就透過使用 SET 命令和 Lua 指令碼在 Redis 單節點上完成了分散式鎖的加鎖和解鎖。
基於 Redis 實現分散式鎖的優點:
基於 Redis 實現分散式鎖的缺點:
為了保證叢集環境下分散式鎖的可靠性,Redis 官方已經設計了一個分散式鎖演算法 Redlock(紅鎖)。
它是基於多個 Redis 節點的分散式鎖,即使有節點發生了故障,鎖變數仍然是存在的,客戶端還是可以完成鎖操作。
Redlock 演算法的基本思路,是讓客戶端和多個獨立的 Redis 節點依次請求申請加鎖,如果客戶端能夠和半數以上的節點成功地完成加鎖操作,那麼我們就認為,客戶端成功地獲得分散式鎖,否則加鎖失敗。
這樣一來,即使有某個 Redis 節點發生故障,因為鎖的資料在其他節點上也有儲存,所以客戶端仍然可以正常地進行鎖操作,鎖的資料也不會丟失。
Redlock 演算法加鎖三個過程:
加鎖成功後,客戶端需要重新計算這把鎖的有效時間,計算的結果是「鎖的最初有效時間」減去「客戶端為獲取鎖的總耗時(t1)」。
加鎖失敗後,客戶端向所有 Redis 節點發起釋放鎖的操作,釋放鎖的操作和在單節點上釋放鎖的操作一樣,只要執行釋放鎖的 Lua 指令碼就可以了。
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2911720/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 分散式鎖----Redis實現分散式Redis
- Redis實現分散式鎖Redis分散式
- 面試題詳解:如何用Redis實現分散式鎖?面試題Redis分散式
- 【Redis】利用 Redis 實現分散式鎖Redis分散式
- redis分散式鎖的實現Redis分散式
- redis分散式鎖-java實現Redis分散式Java
- Redis之分散式鎖實現Redis分散式
- Redis如何實現分散式鎖Redis分散式
- 分散式鎖之Redis實現分散式Redis
- 利用Redis實現分散式鎖Redis分散式
- redis分散式鎖-SETNX實現Redis分散式
- 分散式鎖實現(一):Redis分散式Redis
- 如何使用Redis實現分散式鎖Redis分散式
- redis分散式鎖實現(golang版)Redis分散式Golang
- Redis優雅實現分散式鎖Redis分散式
- 實現一個 Redis 分散式鎖Redis分散式
- 用 Go + Redis 實現分散式鎖GoRedis分散式
- 基於redis實現分散式鎖Redis分散式
- Redis面試系列:Redis實現分散式鎖Redis面試分散式
- 百度社招面試題——如何用Redis實現分散式鎖面試題Redis分散式
- Redis實現可重入的分散式鎖Redis分散式
- Redis分散式鎖實現Redisson 15問Redis分散式
- 使用Redis分散式鎖實現主備Redis分散式
- Spring Boot Redis 實現分散式鎖,真香!!Spring BootRedis分散式
- 實現一個redis的分散式鎖Redis分散式
- redis實現分散式鎖天然的缺陷Redis分散式
- Redis分散式鎖的原理和實現Redis分散式
- Redis實現分散式鎖那件事Redis分散式
- 利用Python+Redis實現分散式鎖PythonRedis分散式
- Redis分散式鎖的正解實現方式Redis分散式
- 在專案中如何用Redis分散式鎖Redis分散式
- Redis分散式鎖實戰Redis分散式
- 分散式鎖與實現(一)基於Redis實現!分散式Redis
- Redis、Zookeeper實現分散式鎖——原理與實踐Redis分散式
- redis分散式鎖-spring boot aop+自定義註解實現分散式鎖Redis分散式Spring Boot
- Redis實現分散式鎖的幾種方案Redis分散式
- 基於Redis實現一個分散式鎖Redis分散式
- 再談分散式鎖之剖析Redis實現分散式Redis