Apache Ignite 的分布式鎖Distributed Locks的介紹

以下這段內容是關于 Apache Ignite 的分布式鎖(Distributed Locks) 的介紹。這是一個非常重要的功能,用于在分布式系統中協調多個節點對共享資源的并發訪問

下面我們來一步步深入理解它。


🎯 一、一句話理解:什么是 Ignite 分布式鎖?

Ignite 分布式鎖是一個跨多個服務器節點的“互斥鎖”,確保同一時間只有一個節點可以操作某個共享數據(比如緩存中的某個 key)。

? 類比:

  • 就像一把“全球唯一的鑰匙”:只有拿到這把鑰匙的線程才能修改某個數據。
  • 單機環境下用 synchronizedReentrantLock
  • 分布式環境下就需要 IgniteCache.lock() 這種跨 JVM 的鎖

🧩 二、核心概念解析

1?? IgniteCache.lock(key) —— 獲取一個分布式鎖

Lock lock = cache.lock("keyLock");
  • 這個 lock 是一個實現了 java.util.concurrent.locks.Lock 接口的對象。
  • 它不是本地鎖!它是集群范圍內的分布式鎖
  • 當你在 Node A 上調用 lock.lock(),Node B 和 Node C 上試圖對同一個 key 加鎖的線程都會阻塞等待,直到 Node A 釋放鎖。

2?? 使用方式:try-finally 確保釋放

lock.lock();  // 阻塞直到獲取鎖
try {// 安全地操作共享資源cache.put("Hello", 11);cache.put("World", 22);
} finally {lock.unlock(); // 必須釋放,否則死鎖!
}

?? 注意:必須放在 finally 塊中釋放,防止異常導致鎖未釋放,造成死鎖或資源饑餓


3?? lockAll(keys) —— 批量加鎖

Collection<String> keys = Arrays.asList("key1", "key2", "key3");
Lock lock = cache.lockAll(keys);
lock.lock();
try {// 同時鎖定多個 keycache.put("key1", 1);cache.put("key2", 2);cache.put("key3", 3);
} finally {lock.unlock();
}
  • 適用于需要原子性地操作多個 key 的場景。
  • 所有 key 的鎖會一起獲取、一起釋放
  • 避免因部分加鎖成功而導致的數據不一致問題。

🔐 三、為什么需要分布式鎖?

在分布式系統中,多個節點可能同時訪問同一份數據。例如:

場景問題解決方案
多個節點同時更新用戶余額超賣、余額錯亂userId 加分布式鎖
多個節點爭搶執行定時任務重復執行"task-refresh" 加鎖
緩存雙寫一致性緩存和數據庫不一致更新時對 key 加鎖

👉 沒有鎖 → 數據競爭(Race Condition) → 數據錯誤!


?? 四、Atomicity Mode:必須是 TRANSACTIONAL

CacheConfiguration cfg = new CacheConfiguration("myCache");
cfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); // 必須設置
  • Ignite 支持兩種原子性模式:
    • ATOMIC:高性能,無事務支持,不能使用顯式鎖。
    • TRANSACTIONAL:支持事務和顯式分布式鎖

? 如果你在 ATOMIC 模式下調用 cache.lock(),會拋出異常!

? 所以:要用分布式鎖,緩存必須配置為 TRANSACTIONAL 模式。


🔄 五、Locks vs Transactions:鎖與事務的關系

這是最容易混淆的部分,原文說得很清楚:

“Explicit locks are not transactional and cannot be used from within transactions.”

我們來拆解這句話:

? 情況 1:顯式鎖 ≠ 事務鎖

類型顯式鎖 (cache.lock())事務中的鎖
是否可嵌套在事務中? 不可以? 可以
是否自動提交/回滾? 不支持回滾? 支持
如何獲取手動 lock.lock()自動由事務管理器獲取
使用場景非事務性臨界區事務性數據操作

🔴 錯誤寫法(會拋異常):

IgniteTransactions txs = ignite.transactions();
try (Transaction tx = txs.txStart()) {Lock lock = cache.lock("key");lock.lock(); // ? 拋異常!不能在事務中使用顯式鎖cache.put("key", 1);tx.commit();
}

? 情況 2:想要“事務中的顯式鎖”?用 PESSIMISTIC 事務

如果你希望在事務中也能“顯式控制鎖”的行為(比如立即失敗而不是等待),應該使用:

try (Transaction tx = ignite.transactions().txStart(TransactionConcurrency.PESSIMISTIC,  // 悲觀并發控制TransactionIsolation.REPEATABLE_READ)) {// 第一次讀/寫就會自動加鎖Integer val = cache.get("key");cache.put("key", val + 1);tx.commit(); // 提交時釋放鎖
}
悲觀事務(PESSIMISTIC)的特點:
  • get()put()立即嘗試獲取分布式鎖
  • 如果鎖被占用,可以選擇超時失敗(避免無限等待)。
  • 行為類似于“顯式鎖 + 事務”的組合效果。

🧪 六、完整示例:銀行轉賬(防止并發超支)

IgniteCache<String, Integer> cache = ignite.cache("accounts");// 模擬兩個賬戶
String from = "account-A";
String to = "account-B";// 對兩個賬戶加鎖(避免死鎖:按字母順序加鎖)
List<String> sortedKeys = Arrays.asList(from, to).stream().sorted().collect(Collectors.toList());
Lock lock = cache.lockAll(sortedKeys);lock.lock();
try {Integer balanceA = cache.get(from);Integer balanceB = cache.get(to);if (balanceA >= 100) {cache.put(from, balanceA - 100);cache.put(to, balanceB + 100);System.out.println("轉賬成功");} else {System.out.println("余額不足");}
} finally {lock.unlock(); // 釋放所有鎖
}

? 保證了即使多個節點同時發起轉賬,也不會出現“超賣”。


?? 七、注意事項 & 最佳實踐

項目建議
🔒 鎖粒度盡量小(比如按用戶 ID 鎖),避免鎖整個緩存
?? 鎖持有時間越短越好,不要在鎖內做耗時操作(如網絡請求)
💥 異常處理一定要 finally unlock(),建議用 try-with-resources(如果自定義封裝)
🪢 死鎖風險多 key 加鎖時,按固定順序加鎖(如排序)
📈 性能影響分布式鎖涉及網絡通信,頻繁使用會影響性能
🔄 替代方案考慮使用 EntryProcessorinvoke())進行原子更新,避免手動加鎖

? 總結:一句話掌握精髓

Ignite 的 cache.lock(key) 提供了一種簡單、直觀的跨節點互斥機制,讓你像使用本地 ReentrantLock 一樣保護分布式共享資源,但前提是緩存必須是 TRANSACTIONAL 模式,并且不能與事務混用。


🔄 對比總結表

功能cache.lock() 顯式鎖悲觀事務(PESSIMISTIC)EntryProcessor(invoke)
是否跨節點? 是? 是? 是
是否支持事務? 否? 是? 是(單 key)
是否自動加鎖? 手動? 自動? 自動
適用場景非事務臨界區多 key 事務操作單 key 原子更新
性能中等中等高(推薦)

如果你想實現高并發下的安全更新,優先考慮 EntryProcessor;如果邏輯復雜必須加鎖,再用 lock() 或 悲觀事務。

如有具體業務場景(如庫存扣減、計數器、任務調度),歡迎繼續提問,我可以給出更具體的代碼建議!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91295.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十二天:C++ 標準庫函數分類總結

C 標準庫函數分類總結 數學函數&#xff08;<cmath>&#xff09; 基本運算函數 abs(x)&#xff1a;返回整數或浮點數的絕對值。int a abs(-5); // 返回 5fabs(x)&#xff1a;返回浮點數的絕對值。double b fabs(-3.14); // 返回 3.14fmod(x, y)&#xff1a;計算 x 除以…

Unity Standard Shader 解析(四)之ForwardAdd(簡化版)

一、ForwardAdd// Additive forward pass (one light per pass)Pass{Name "FORWARD_DELTA"Tags { "LightMode" "ForwardAdd" }Blend [_SrcBlend] OneFog { Color (0,0,0,0) } // in additive pass fog should be blackZWrite OffZTest LEqualC…

第十九周-文檔數據庫MongoDB、消息隊列和微服務

1. 完成redis單機安裝&#xff0c;哨兵模式安裝&#xff0c;主從安裝&#xff0c;集群安裝單機安裝#安裝依賴包 [rootcentos8~]#yum -y install gcc make jemalloc-devel #如果支持systemd需要安裝下面包 [rootubuntu2204 ~]#apt update && apt -y install make gcc li…

C++中sizeof運算符全面詳解和代碼示例

sizeof 是 C 中的一個編譯時運算符&#xff0c;用于獲取對象或類型所占的字節數&#xff08;以 size_t 返回&#xff09;。它是掌握底層內存模型、結構體對齊、數組大小計算等的重要工具。1. 基本語法 sizeof(type) // 獲取類型的大小 sizeof expression // 獲取表達式結果…

內容中臺:在一個地方管理多渠道內容

在數字化競爭愈演愈烈的今天&#xff0c;企業官網、社交平臺、移動應用、郵件營銷等渠道已成為品牌觸達用戶的關鍵接口。內容仍是連接企業與客戶的核心資產。然而&#xff0c;內容創作與分發的復雜性持續攀升&#xff0c;多平臺運營面臨重復維護、更新不一致、資源冗余等諸多挑…

【刷題】東方博宜oj 1307 - 數的計數

樣例輸入&#xff1a; 6輸出&#xff1a; 16 26 126 36 136原版是直接輸出總數量&#xff0c;但我修改了一些&#xff0c;輸出所有的新數。 #include <iostream> #include <vector> #include <string> using namespace std; //int c; void g(int num, string…

阿里云AI代碼助手通義靈碼開發指導

與阿里云一起輕松實現數智化讓算力成為公共服務&#xff1a;用大規模的通用計算&#xff0c;幫助客戶做從前不能做的事情&#xff0c;做從前做不到的規模。讓數據成為生產資料&#xff1a;用數據的實時在線&#xff0c;幫助客戶以數據為中心改變生產生活方式創造新的價值。智能…

設計模式(二十三)行為型:模板方法模式詳解

設計模式&#xff08;二十三&#xff09;行為型&#xff1a;模板方法模式詳解模板方法模式&#xff08;Template Method Pattern&#xff09;是 GoF 23 種設計模式中的行為型模式之一&#xff0c;其核心價值在于定義一個操作中的算法骨架&#xff0c;而將一些步驟延遲到子類中實…

Postgresql 查詢使用正則

今天接到任務&#xff0c;要從數據庫中查詢數據&#xff0c;對于postgresql 我并不熟悉&#xff0c;問了百度&#xff0c;問了通義千問。發現Postgresql 在寫query sql 的時候&#xff0c;可以使用正則匹配&#xff0c;不單是使用like 這種關鍵字。我像發現了新大陸一樣的興奮。…

【WRF-Chem Emissions教程第八期】轉換實用程序

轉換實用程序 8.1 將中間二進制文件轉換為 WRF-Chem 數據文件 文件命名規范與風格 8.2 Binary data file format(中間二進制排放數據文件的格式和結構) FORTRAN 示例程序說明 8.3 Building the WRF-Chemistry emissions conversion code 編譯步驟 驗證編譯結果 8.4 Namelist …

Qt Ribbon效果界面

實現效果&#xff1a;頭文件&#xff1a;#pragma once #include <QMdiArea> #include <QMdiSubWindow> #include <QMainWindow> #include "ui_MainFrame1.h" #include "DockManager.h" #include "DockAreaWidget.h"class Main…

如何修改 MySQL 8.0 的密碼,和忘記密碼時如何修改

要修改 MySQL 8.0 的密碼&#xff0c;可以通過以下幾種方法實現&#xff1a;方法 1&#xff1a;使用 ALTER USER 命令&#xff08;推薦&#xff09;這是 MySQL 8.0 推薦的修改密碼方式&#xff1a;-- 修改當前登錄用戶的密碼 ALTER USER USER() IDENTIFIED BY 新密碼;-- 修改指…

圖像處理控件Aspose.Imaging教程:使用 C# 編程將 CMX 轉換為 PNG

PNG圖像文件格式是廣泛使用的圖像格式之一。這種圖像文件格式提供了增強的共享和顯示功能。另一方面&#xff0c;CMX也是 Corel 應用程序主要使用的圖像文件格式。然而&#xff0c;將 CMX 轉換為 PNG 可以幫助用戶在網絡上查看和共享文件。因此&#xff0c;在本指南中&#xff…

迪麗熱巴寫真壁紙

下載&#xff1a;https://pan.quark.cn/s/a740dbac8274迪麗熱巴絕美寫真&#xff0c;高清壁紙展現獨特魅力&#xff0c;每一張都是視覺盛宴

C++11 std::function 詳解:通用多態函數包裝器

在C11標準中&#xff0c;引入了std::function這一通用多態函數包裝器&#xff0c;定義于<functional>頭文件中。它徹底改變了C中函數對象的使用方式&#xff0c;為不同類型的可調用實體提供了統一的接口。std::function能夠存儲、復制和調用任何可復制構造的可調用目標&a…

Kafka運維實戰 16 - kafka 分區重新分配【實戰】

?? Kafka運維實戰 (17篇) ??Kafka運維實戰 17 - kafka 分區副本從 1 增加到 3【實戰】 ??Kafka運維實戰 16 - kafka 分區重新分配【實戰】 ??Kafka運維實戰 15 - kafka 重設消費者組位移入門和實戰【實戰】 ??Kafka運維實戰 14 - kafka消費者組消費進度(Lag)深入理…

智匯AI,應用領航 | 華宇萬象問數入選2025全景賦能典型案例

7月29日&#xff0c;以“AI城市&#xff1a;數啟新紀元”為主題中關村人工智能與未來城市論壇在中關村國家自主創新示范區展示中心舉辦。本次論壇圍繞人工智能創新應用落地實踐、新型數據基礎設施建設、數據要素價值釋放機制、城市智能治理等關鍵議題&#xff0c;邀請院士專家和…

sqli-labs:Less-7關卡詳細解析

1. 思路&#x1f680; 本關的SQL語句為&#xff1a; $sql"SELECT * FROM users WHERE id(($id)) LIMIT 0,1";注入類型&#xff1a;字符串型&#xff08;單引號、雙括號包裹&#xff09;提示&#xff1a;參數id需以))閉合 同樣無法像常規一樣回顯&#xff0c;php輸出語…

編程算法:從理論基石到產業變革的核心驅動力

文章目錄 算法的本質與效率衡量 基礎算法范式的實踐價值 排序算法的演進與選擇 動態規劃的實用技巧 算法在現代技術棧中的應用 大數據處理的算法框架 編譯器中的算法優化 算法驅動的產業變革 金融領域的算法應用 醫療健康領域的算法創新 制造業的算法優化 算法的未來趨勢 結語 …

深度學習中的注意力機制:原理、應用與未來展望

在人工智能領域&#xff0c;深度學習技術已經取得了巨大的突破&#xff0c;而注意力機制&#xff08;Attention Mechanism&#xff09;作為深度學習中的一個重要概念&#xff0c;正在逐漸改變我們對模型的理解和應用。本文將深入探討注意力機制的原理、在不同領域的應用以及未來…