動態

詳情 返回 返回

別隻怪客户端宕機!還有這些導致 Redis 分佈式鎖“死鎖”的原因 - 動態 詳情

本文已收錄在Github,關注我,緊跟本系列專欄文章,咱們下篇再續!

  • 🚀 魔都架構師 | 全網30W技術追隨者
  • 🔧 大廠分佈式系統/數據中台實戰專家
  • 🏆 主導交易系統百萬級流量調優 & 車聯網平台架構
  • 🧠 AIGC應用開發先行者 | 區塊鏈落地實踐者
  • 🌍 以技術驅動創新,我們的征途是改變世界!
  • 👉 實戰乾貨:編程嚴選網

0 前言

除了“持有鎖的進程崩潰、未釋放鎖”這一經典場景,還會因以下容易被忽視的問題,導致系統進入類似死鎖的阻塞狀態:

1 客户端本地時鐘漂移

若加鎖客户端的系統時間被人為或自動回撥,可能導致鎖的本地過期時間計算錯誤,客户端誤以為鎖已過期而提前續期或釋放,其他客户端趁機搶佔,造成多客户端同時持有同一把鎖,後續釋放時又互相覆蓋,最終誰都無法正常完成業務,表現得像死鎖。

解決方案

啓用 NTP 嚴格同步,或使用 monotonic 時間源;

2 鎖續期(看門狗)異常

Redisson“看門狗”機制依賴後台線程週期性地為鎖續期。若業務線程因 GC、CPU 調度或網絡抖動被長時間掛起,看門狗線程也隨之暫停,鎖在 Redis 端真正過期;業務恢復後卻仍認為鎖有效,繼續持有,導致後續競爭者無法獲取鎖,形成阻塞。

解決方案

限制業務邏輯執行時間,設置合理的 watchdog 超時上限。

3 主從切換期間的鎖丟失

Redis主從異步複製下:

  • 主節點加鎖成功後宕機
  • 從節點升為主但尚未收到該鎖的寫入

新客户端在新【主節點】上再次加鎖成功,兩個客户端同時持有同一把鎖;當它們都嘗試釋放鎖時,可能互相刪除對方的鍵,造成業務邏輯混亂,後續請求因鎖狀態不一致而持續等待。

解決方案

啓用 Redis 哨兵或集羣模式,結合 RedLock 多數派策略。

4 Lua 腳本執行超時

用 Lua 腳本保證“判斷-刪除”原子性時,若腳本因數據量過大或邏輯複雜執行時間超過 Redis 的 lua-time-limit,Redis 會中斷腳本並記錄 EVALSHA 失敗,但客户端可能未收到失敗信號,繼續認為鎖已釋放;其他客户端因鍵仍存在而無法加鎖,系統出現“假死”狀態。

解決方案

拆分複雜腳本,縮短執行時間,或改用 pipeline 分批執行。

Add a new 評論

Some HTML is okay.