大家好,我是小米,今年 31 歲,一個在 Java 世界裏摸爬滾打多年的程序員大哥哥。
前幾天,我在幫朋友模擬社招面試的時候,面試官突然拋出一個問題:
“你瞭解 Redis 的 RedLock 嗎?它解決了什麼問題?”
朋友愣了三秒鐘,憋出一句:
“呃……分佈式鎖的一種實現?”
面試官點點頭,又補了一刀:
“那為什麼要有 RedLock?SETNX 不行嗎?”
好,熟悉的氣息來了。這是一個典型的:面試官想看看你“到底理解到哪一層”的問題。
今天這篇文章,我不打算一上來就甩論文、甩算法、甩名詞。我們還是老規矩講個故事。
故事的開始:全村只有一把鎖
想象一個場景。你住在一個村子裏,村裏有一間公共倉庫,裏面放着村裏唯一的“寶貝資源”:比如水泵、電動車充電口、發電機。
為了避免大家同時搶,村長規定:誰用,誰先拿鎖。這把鎖就掛在倉庫門口。
單機時代:一把鎖,世界和平
一開始,村子很小,只有一個倉庫。
- 鎖是真的鎖
- 鑰匙只有一把
- 誰先拿到,誰用
這就像:單體應用 + 本地鎖(synchronized / ReentrantLock)
簡單、直接、世界和平。
問題來了:村子擴張了(分佈式時代)
後來,村子發展了。
- 東村
- 西村
- 南村
- 北村
每個村口都建了一個倉庫副本,數據是同步的。於是問題來了:“鎖放哪?”
如果還只有一把鎖,大家跑來跑去,效率極低。於是村長拍板:“每個倉庫門口,都放一把鎖!”
聽起來很合理,對吧?
Redis 分佈式鎖的第一形態:SETNX
這時候,我們就進入了Redis 分佈式鎖的基礎階段。
Redis 單節點鎖的思路
在 Redis 裏,我們通常這麼做:
含義是:
- NX:只有不存在才設置(加鎖)
- PX:設置過期時間(防止死鎖)
Java 示例代碼:
這套方案,在單 Redis 實例下,基本可用。
單點問題:鎖的“唯一倉庫”塌了
故事開始變得刺激。有一天,西村倉庫塌了(Redis 宕機)。發生了什麼?
- 鎖沒了
- 其他人以為“鎖不存在”
- 大家一起衝進倉庫
問題本質:單個 Redis 節點 = 單點故障
只要 Redis 掛了:
- 鎖狀態丟失
- 分佈式一致性直接破產
進階方案:主從 + 哨兵,夠了嗎?
你可能會説:“那我用 Redis 主從 + 哨兵不就好了?”
這是一個非常典型的面試陷阱點,主從複製的時間差問題。
Redis 的主從複製是:異步複製。想象這個場景:
- 客户 A 在 Master 上加鎖成功
- Master 還沒來得及同步給 Slave
- Master 宕機
- Slave 被提升為 Master
- 客户 B 再次加鎖成功
結果是:兩個客户端,同時持有“同一把鎖”
故事轉折:村長髮明瞭“五把鎖機制”
這時候,村長終於意識到:“不能只信一把鎖了。”
於是他提出一個瘋狂的方案:在 5 個獨立的倉庫裏,各放一把鎖,誰能同時拿到其中 3 把,誰才算真的拿到鎖。”
這,就是 RedLock 的核心思想。
什麼是 RedLock?一句話説清楚
RedLock 是 Redis 作者提出的一種基於多個獨立 Redis 節點的分佈式鎖算法,通過“多數派原則”來提升鎖的可靠性。
關鍵詞拆解一下:
RedLock 的加鎖流程(面試必考)
RedLock 的加鎖流程,面試官最愛問。
加鎖步驟
假設有 5 個 Redis 節點:
1、記錄當前時間 T1
2、依次向 5 個 Redis 節點嘗試加鎖
3、每個節點使用相同的:
- key
- value
- 過期時間
4、如果:
- 成功節點 ≥ 3
- 且總耗時 < 鎖過期時間
5、則加鎖成功
6、否則:
- 向已成功的節點釋放鎖
- 加鎖失敗
RedLock 的核心判斷條件(表格版)
RedLock Java 代碼示例(基於 Redisson)
現實中,我們不建議手寫 RedLock。最常用的是 Redisson。
1、Maven 依賴
2、配置多個 Redis 節點
3、使用 RedLock
RedLock 的優點和爭議(高階加分點)
優點
爭議(面試官最喜歡的)
Redis 官方作者提出,但學術界和工程界一直有爭論:
- 網絡分區問題
- 時間漂移問題
- 鎖有效性依賴系統時間
Martin Kleppmann 曾公開質疑:“RedLock 並不能在所有情況下保證安全性。”
面試官真正想聽的答案是什麼?
當面試官問:“你怎麼看 RedLock?”
一個成熟的回答是:
- RedLock 適合高可用場景
- 成本較高,複雜度高
- 並非強一致性方案
- 是否使用,取決於業務容錯能力
總結
最後,用一句話總結:
RedLock 不是銀彈,它只是在“可用性”和“複雜度”之間,給出的一種工程折中方案。
如果你的業務:
- 能容忍極小概率的鎖失效
- 對可用性要求極高
RedLock 值得考慮。
如果你的業務:
- 對一致性要求極端嚴格
- 不能接受任何併發錯誤
請考慮 數據庫鎖 / Zookeeper。
END
我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!