現在越來越多團隊傾向把狀態、快取、排行榜、暫存資料通通往 Redis 塞。理由很簡單:Redis 快、簡單、大家都會用。但你有想過嗎?當多人或多實例同時修改同一筆 Redis 資料,資料就可能被覆蓋、異常或損毀。
本篇文章將以實作為主,示範一個用 Go 實作的 RedisLocker
工具,協助你在 Redis 中安全地進行單一資源互斥修改。這不是 Redlock,而是更簡單、輕量又夠用的解法,適合大多數「把資料都往 Redis 塞」的情境。
為什麼 Redis 裡的資料還需要加鎖?
你可能會說:「我用 Lua script 操作 get + set,不是已經原子了嗎?」是的,Lua script 能確保指令的原子性,但它無法防止多個 client 同時讀 + 寫同一筆資料。若沒有鎖,還是可能發生以下狀況:
- Client A 和 B 幾乎同時讀出相同的舊值
- 分別修改後各自寫回,造成資料覆蓋、遺失
這種 race condition,在高併發或多服務架構中非常常見,尤其是當你把整個 JSON 結構塞進 Redis、拿出來處理再寫回的時候,不加鎖幾乎是災難。
分散式鎖核心設計
以下是 RedisLocker
的核心程式碼(簡化說明):

上鎖:SetNX
加唯一 token

- 使用
uuid
為每次鎖定生成獨立 token。 - 如果成功取得鎖,執行
fn()
所代表的邏輯區塊。 - 用
defer
保證結束時釋放鎖。
解鎖:Lua 腳本確保安全

- 使用 Lua 腳本確保只有擁有該 token 的流程可以解鎖,防止誤刪他人鎖定。
應用實例:避免重複執行複雜邏輯

在這個例子中,我們用 RedisLocker 包住一段會修改 Redis 資料的邏輯,確保同一時間只會有一個執行緒操作 lockKey
,避免寫入錯亂或資源衝突。
myComplexFunction()
負責從 Redis 讀取 JSON 資料、解碼、修改、再寫回。若在高併發情境下未加鎖,容易造成 race condition 或資料損毀。
完整資料結構

為什麼不用 Redlock?
Redis 官方有提出更嚴謹的 Redlock 演算法,但在大多數內部服務(如只有一組 Redis)中,簡單的 SETNX + token
實作已可滿足需求。此範例屬於 lightweight 應用,易於理解與實作。
小結
這篇文章分享了一個可應用在實務開發中的 Golang Redis 分散式鎖範例,涵蓋:
- 基本鎖定/解鎖邏輯
- Lua 腳本防止 token 衝突
- 真實場景的應用示範
你可以將 RedisLocker
封裝成一個工具套件,應用在批次任務、同步操作、隊列處理等場景。
完整範例程式碼可見於 GitHub Gist:[RedisLocker 實作]
延伸閱讀
- Redis 官方文檔 - SETNX
- Redis 分散式鎖設計 - Redlock Algorithm