你有聽說過 Redlock 嗎?
別整些花裡胡哨的,Redlock 全稱 Redis Distributed Lock,即用 Redis 實現的分佈式鎖。
Redis 熱身知識
Redis 命令參考:http://doc.redisfans.com/index.html
面試中經常聽到說用 SETNX 做分佈式鎖,我們在 Redis 客戶端裡看看
setnx 是 SET if Not eXists (如果不存在,則 SET) 的簡寫。
1、 SETNX
從圖中,如果 key 不存在,返回 1,存在,返回 0;
2、SETEX
SETNX key seconds value
Redis setex 命令為指定的 key 設置值及其過期時間。如果 key 已經存在, SETEX 命令將會替換舊的值。
setex 是一個原子性操作
其中 ttl (Time To Live),命令以秒為單位返回 key 的剩餘過期時間,負數表示已過期。
3、PSETEX
PSETEX key milliseconds value
這個命令和 SETEX 命令相似,但它以毫秒為單位設置 key 的生存時間,而不是像 SETEX 命令那樣,以秒為單位。pttl 命令以毫秒為單位返回 key 的剩餘過期時間,負數表示已過期。
注意:
從 Redis 2.6.12 版本開始, SET 命令的行為可以通過一系列參數來修改。
因為 SET 命令可以通過參數來實現和 SETNX 、 SETEX 和 PSETEX 三個命令的效果,所以將來的 Redis 版本可能會廢棄並最終移除 SETNX 、 SETEX 和 PSETEX 這三個命令。
SET key value [EX seconds] [PX milliseconds] [NX|XX]
① EX second :設置鍵的過期時間為 second (秒)。 SET key value EX second 效果等同於 SETEX key second value 。
② PX millisecond :設置鍵的過期時間為 millisecond 毫秒。 SET key value PX millisecond 效果等同於 PSETEX key millisecond value 。
③ NX :只在鍵不存在時,才對鍵進行設置操作。 SET key value NX 效果等同於 SETNX key value 。
④ XX :只在鍵已經存在時,才對鍵進行設置操作。
4、推薦使用 SET NX PX 獲取鎖
SET key value NX PX 6000
我們在實際項目中,還會增加一個獲取鎖的時間,去循環獲取鎖。
注意:
key : 資源名字,加鎖對象的唯一標記。
value: 通常存儲加鎖方的唯一標記,如 “UUID+ThreadID”。是由客戶端生成的一個隨機字符串,相當於是客戶端持有鎖的標誌。
先思考下,為什麼 value 要設置為唯一標記???
5、採用 Lua 腳本來釋放鎖
Lua 腳本是原子性的,成功返回 1 ,失敗返回 0;
KEYS [1] 的值為 key,ARGV [1] 的值為 value。原理就是先獲取 lock 對應的 value 值,保證和客戶端穿進去的 value 值相等,相等的時候才會執行 del 命令釋放鎖。
注意:
① 為什麼 value 要設置為唯一標記???
如果不設置成唯一標記,那客戶端 2 可能釋放掉客戶端 1 的鎖;
② 為什麼釋放 lock 用 Lua 腳本?
釋放 lock 經歷的步驟:
① 獲取 key 對應的值 value;
② 判斷 value 是否和客戶端生成的隨機值一樣;
③ 如果一樣,執行 del 命令
這三步非原子性操作,如果不使用 Lua 腳本,由於鎖有過期時間,會出現如下圖的情況。
客戶端 1 先獲取鎖,執行到了第 ② 步,但是卡住了,鎖失效。
客戶端 2 獲取鎖,執行任務中;
客戶端 1 執行了 del 命令,會釋放客戶端 2 的鎖。
以上屬於 Redis 面試中的熱身問題,送分題啊,朋友們!
如果有不對的地方,歡迎評論留言指正,有話你就說啊。如果對你有幫助,轉發點贊收藏一波,下節繼續分析分佈式鎖中問題,關注 @Python大星 ,一個會點 Python 的 Java 程序猿。
@Python大星 | 文