Golang + Redis:給「什麼都往 Redis 塞」的你,一個安全修改資料的分散式鎖範例

更新於 發佈於 閱讀時間約 4 分鐘

現在越來越多團隊傾向把狀態、快取、排行榜、暫存資料通通往 Redis 塞。理由很簡單:Redis 快、簡單、大家都會用。但你有想過嗎?當多人或多實例同時修改同一筆 Redis 資料,資料就可能被覆蓋、異常或損毀。

本篇文章將以實作為主,示範一個用 Go 實作的 RedisLocker 工具,協助你在 Redis 中安全地進行單一資源互斥修改。這不是 Redlock,而是更簡單、輕量又夠用的解法,適合大多數「把資料都往 Redis 塞」的情境。

為什麼 Redis 裡的資料還需要加鎖?

你可能會說:「我用 Lua script 操作 get + set,不是已經原子了嗎?」

是的,Lua script 能確保指令的原子性,但它無法防止多個 client 同時讀 + 寫同一筆資料。若沒有鎖,還是可能發生以下狀況:

  • Client A 和 B 幾乎同時讀出相同的舊值
  • 分別修改後各自寫回,造成資料覆蓋、遺失

這種 race condition,在高併發或多服務架構中非常常見,尤其是當你把整個 JSON 結構塞進 Redis、拿出來處理再寫回的時候,不加鎖幾乎是災難


分散式鎖核心設計

以下是 RedisLocker 的核心程式碼(簡化說明):

raw-image

上鎖:SetNX 加唯一 token

raw-image
  • 使用 uuid 為每次鎖定生成獨立 token。
  • 如果成功取得鎖,執行 fn() 所代表的邏輯區塊。
  • defer 保證結束時釋放鎖。

解鎖:Lua 腳本確保安全

raw-image
  • 使用 Lua 腳本確保只有擁有該 token 的流程可以解鎖,防止誤刪他人鎖定。

應用實例:避免重複執行複雜邏輯

raw-image

在這個例子中,我們用 RedisLocker 包住一段會修改 Redis 資料的邏輯,確保同一時間只會有一個執行緒操作 lockKey,避免寫入錯亂或資源衝突。

myComplexFunction() 負責從 Redis 讀取 JSON 資料、解碼、修改、再寫回。若在高併發情境下未加鎖,容易造成 race condition 或資料損毀。


完整資料結構

raw-image



為什麼不用 Redlock?

Redis 官方有提出更嚴謹的 Redlock 演算法,但在大多數內部服務(如只有一組 Redis)中,簡單的 SETNX + token 實作已可滿足需求。此範例屬於 lightweight 應用,易於理解與實作。


小結

這篇文章分享了一個可應用在實務開發中的 Golang Redis 分散式鎖範例,涵蓋:

  • 基本鎖定/解鎖邏輯
  • Lua 腳本防止 token 衝突
  • 真實場景的應用示範

你可以將 RedisLocker 封裝成一個工具套件,應用在批次任務、同步操作、隊列處理等場景。

完整範例程式碼可見於 GitHub Gist:[RedisLocker 實作]


延伸閱讀

留言
avatar-img
留言分享你的想法!
avatar-img
虎斑貓的散記
5會員
11內容數
量化研究心得,社會觀察,自我反思
虎斑貓的散記的其他內容
2025/07/02
最近在教學 Golang 的記憶體處理細節時,重新對 Pointer 和 Pointer Receiver 做了梳理。這兩者經常一起出現,但實際上代表不同層面的設計。
2025/07/02
最近在教學 Golang 的記憶體處理細節時,重新對 Pointer 和 Pointer Receiver 做了梳理。這兩者經常一起出現,但實際上代表不同層面的設計。
2025/07/01
Go 語言中的 init() 函式於 package 匯入時自動執行,import _ "..." 技巧則允許僅執行 init() 函式而避免使用該 package 的其他內容。
2025/07/01
Go 語言中的 init() 函式於 package 匯入時自動執行,import _ "..." 技巧則允許僅執行 init() 函式而避免使用該 package 的其他內容。
2021/09/23
傳統上,我們認為付出努力即可逐步接近目標,但在機器學習中,追求完美可能導致整體效能下降。,有時捨棄少量極端值,換取大幅提升整體模型表現更為實際。
Thumbnail
2021/09/23
傳統上,我們認為付出努力即可逐步接近目標,但在機器學習中,追求完美可能導致整體效能下降。,有時捨棄少量極端值,換取大幅提升整體模型表現更為實際。
Thumbnail
看更多
你可能也想看
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
GOB Go官方有提供net/rpc的RPC套件。此套件提供GOB的編/解碼,且支援TCP或HTTP傳輸方式。它可以在伺服器端註冊多個不同類型物件。 遠端存取的要求條件 方法的類型可輸出 方法的本體可輸出 方法必須要有兩個參數是輸出或內建 方法的第二個參數是指標型 方法的返回類型為
Thumbnail
GOB Go官方有提供net/rpc的RPC套件。此套件提供GOB的編/解碼,且支援TCP或HTTP傳輸方式。它可以在伺服器端註冊多個不同類型物件。 遠端存取的要求條件 方法的類型可輸出 方法的本體可輸出 方法必須要有兩個參數是輸出或內建 方法的第二個參數是指標型 方法的返回類型為
Thumbnail
支援Go所有的類型儲存,且可以用原生SQL敘述與跨資料庫查詢。 映射關係 table->struct record->object field->attribute 安裝 go get github.com/astaxie/beego/orm​ go get github.com
Thumbnail
支援Go所有的類型儲存,且可以用原生SQL敘述與跨資料庫查詢。 映射關係 table->struct record->object field->attribute 安裝 go get github.com/astaxie/beego/orm​ go get github.com
Thumbnail
本篇將分享VSCode工作區的設定與功能,包括如何將資料夾新增到工作區、如何存檔、以及外掛推薦。這些小技巧能夠幫助您在使用 rushjs 能更輕鬆地管理 monorepo,提高工作效率。
Thumbnail
本篇將分享VSCode工作區的設定與功能,包括如何將資料夾新增到工作區、如何存檔、以及外掛推薦。這些小技巧能夠幫助您在使用 rushjs 能更輕鬆地管理 monorepo,提高工作效率。
Thumbnail
抓取對象檔案,自動進行壓縮處理,壓縮後產出一個壓縮檔案,如此便可節省硬碟使用空間
Thumbnail
抓取對象檔案,自動進行壓縮處理,壓縮後產出一個壓縮檔案,如此便可節省硬碟使用空間
Thumbnail
題目敘述 題目會給我們一組定義好的界面和需求,要求我們設計一個資料結構,可以滿足平均O(1)的插入元素、刪除元素、隨機取得元素的操作。 RandomizedSet() 類別建構子 bool insert(int val) 插入元素的function界面 bool remove(int val
Thumbnail
題目敘述 題目會給我們一組定義好的界面和需求,要求我們設計一個資料結構,可以滿足平均O(1)的插入元素、刪除元素、隨機取得元素的操作。 RandomizedSet() 類別建構子 bool insert(int val) 插入元素的function界面 bool remove(int val
Thumbnail
大數據時代下,Log的多元應用至關重要。Log生成龐大,格式各異,特別金融業需合規。探討Log廣泛應用、資訊安全、IT管理和商業決策。建立Log管理系統核心深入法規,強化IT治理、權限控管。一站式Log管理平台,確保資訊安全合規。
Thumbnail
大數據時代下,Log的多元應用至關重要。Log生成龐大,格式各異,特別金融業需合規。探討Log廣泛應用、資訊安全、IT管理和商業決策。建立Log管理系統核心深入法規,強化IT治理、權限控管。一站式Log管理平台,確保資訊安全合規。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News