首頁 科技週邊 IT業界 Java和MongoDB 4.0支持多文件酸交易

Java和MongoDB 4.0支持多文件酸交易

Feb 16, 2025 pm 12:36 PM

MongoDB 4.0 的多文檔 ACID 事務支持詳解

Java and MongoDB 4.0 Support for Multi-document ACID Transactions

(本文與 MongoDB 合作創作。感謝您支持使 SitePoint 成為可能的合作夥伴。)

MongoDB 4.0 新增了對多文檔 ACID 事務的支持。但這是否意味著 MongoDB 此前不支持事務?並非如此,MongoDB 一直以來都支持單文檔事務。 MongoDB 4.0 將這些事務保證擴展到多個文檔、多個語句、多個集合和多個數據庫。如果沒有某種形式的事務數據完整性保證,數據庫還有什麼用呢?

在深入探討本文之前,您可以在這裡找到所有代碼並嘗試多文檔 ACID 事務。

關鍵要點

  • MongoDB 4.0 引入了多文檔 ACID 事務,將事務保證擴展到多個文檔、語句、集合和數據庫,從而增強數據完整性和一致性。
  • 在 MongoDB 4.0 之前,MongoDB 支持單文檔事務,確保單個文檔內的原子操作,適用於大多數應用程序。
  • MongoDB 4.0 中的多文檔 ACID 事務與傳統關係數據庫事務一致,在更複雜的操作中提供原子性、一致性、隔離性和持久性。
  • 使用多文檔 ACID 事務的設置包括啟動 MongoDB ReplicaSet,設置具有必要依賴項的 Java 環境,以及通過提供的腳本執行事務操作。
  • 文章中的實際演示展示了多文檔事務的實現,包括根據庫存可用性提交或回滾事務的場景,確保數據庫狀態一致性。

快速入門

步驟 1:啟動 MongoDB

在 localhost 的 27017 端口上啟動版本至少為 4.0.0 的單節點 MongoDB ReplicaSet。

如果您使用 Docker:

  • 您可以使用 start-mongo.sh
  • 完成後,您可以使用 stop-mongo.sh
  • 如果您想使用 Mongo Shell 連接到 MongoDB,您可以使用 connect-mongo.sh

如果您更喜歡手動啟動 mongod:

  • mkdir /tmp/data && mongod --dbpath /tmp/data --replSet rs
  • mongo --eval 'rs.initiate()'

步驟 2:啟動 Java

此演示包含兩個主程序:ChangeStreams.javaTransactions.java

  • Change Streams 允許您接收 MongoDB 集合或數據庫中任何數據更改的通知。
  • 事務過程是演示本身。

您需要兩個 shell 來運行它們。

如果您使用 Docker:

第一個 shell:

./compile-docker.sh
./change-streams-docker.sh
登入後複製
登入後複製
登入後複製

第二個 shell:

./transactions-docker.sh
登入後複製
登入後複製
登入後複製

如果您不使用 Docker,則需要安裝 Maven 3.5.X 和 JDK 10(或 JDK 8 最低版本,但您需要更新 pom.xml 中的 Java 版本):

第一個 shell:

./compile-docker.sh
./change-streams-docker.sh
登入後複製
登入後複製
登入後複製

第二個 shell:

./transactions-docker.sh
登入後複製
登入後複製
登入後複製

讓我們將現有的單文檔事務與 MongoDB 4.0 的 ACID 兼容多文檔事務進行比較,並了解如何使用 Java 利用此新功能。

MongoDB 4.0 之前的版本

即使在 MongoDB 3.6 和更早版本中,每個寫入操作都表示為作用域在存儲層單個文檔級別的交易。由於文檔模型將相關數據組合在一起,否則這些數據會在表格模式中跨不同的父子表建模,因此 MongoDB 的原子單文檔操作提供滿足大多數應用程序數據完整性需求的事務語義。

每個修改多個文檔的典型寫入操作實際上都會發生在幾個獨立的事務中:每個文檔一個事務。

讓我們以一個非常簡單的庫存管理應用程序為例。

首先,我需要一個 MongoDB Replica Set,因此請按照上面給出的說明啟動 MongoDB。

現在讓我們將以下文檔插入到產品集合中:

./compile.sh
./change-streams.sh
登入後複製
登入後複製

假設正在進行促銷活動,我們想為客戶提供所有產品的 20% 折扣。

但在應用此折扣之前,我們想使用 Change Streams 監控這些操作在 MongoDB 中發生的時間。

在 Mongo Shell 中執行以下操作:

./transactions.sh
登入後複製

將此 shell 保留在一邊,打開另一個 Mongo Shell 並應用折扣:

MongoDB Enterprise rs:PRIMARY> db.product.insertMany([
    { "_id" : "beer", "price" : NumberDecimal("3.75"), "stock" : NumberInt(5) }, 
    { "_id" : "wine", "price" : NumberDecimal("7.5"), "stock" : NumberInt(3) }
])
登入後複製

如您所見,兩個文檔都使用單個命令行進行了更新,但並非在一個事務中。以下是我們在 Change Stream shell 中看到的:

cursor = db.product.watch([{$match: {operationType: "update"}}]);
while (!cursor.isExhausted()) {
  if (cursor.hasNext()) {
    print(tojson(cursor.next()));
  }
}
登入後複製

如您所見,這兩個操作的集群時間(請參見 clusterTime 密鑰)不同:這些操作發生在同一秒內,但時間戳的計數器已遞增 1。

因此,這裡每個文檔一次更新一個,即使這發生得非常快,其他人也可能在更新運行時讀取文檔,並且只能看到其中一種產品有折扣。

大多數情況下,這是您可以在 MongoDB 數據庫中容忍的事情,因為我們盡可能嘗試將緊密關聯或相關的數據嵌入到同一個文檔中。因此,對同一文檔的兩次更新在一個事務中發生:

PRIMARY> db.product.updateMany({}, {$mul: {price:0.8}})
{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
PRIMARY> db.product.find().pretty()
{
    "_id" : "beer",
    "price" : NumberDecimal("3.00000000000000000"),
    "stock" : 5
}
{
    "_id" : "wine",
    "price" : NumberDecimal("6.0000000000000000"),
    "stock" : 3
}
登入後複製

但是,有時您無法將所有相關數據建模到單個文檔中,並且有很多理由選擇不嵌入文檔。

使用多文檔 ACID 事務的 MongoDB 4.0

MongoDB 中的多文檔 ACID 事務與您可能已經從傳統關係數據庫中了解到的非常相似。

MongoDB 的事務是一組相關的對話式操作,必須以全有或全無的執行方式原子地提交或完全回滾。

事務用於確保操作即使跨多個集合或數據庫也是原子的。因此,使用快照隔離讀取,另一個用戶只能看到所有操作或沒有操作。

現在讓我們向我們的示例中添加一個購物車。

在此示例中,需要 2 個集合,因為我們正在處理 2 個不同的業務實體:庫存管理和每個客戶端在購物期間可以創建的購物車。這些集合中每個文檔的生命週期都不同。

產品集合中的文檔表示我正在銷售的商品。這包含產品的當前價格和當前庫存。我創建了一個 POJO 來表示它:Product.java

./compile-docker.sh
./change-streams-docker.sh
登入後複製
登入後複製
登入後複製

當客戶端將其第一個商品添加到購物車時,就會創建購物車,當客戶端繼續結賬或離開網站時,就會刪除購物車。我創建了一個 POJO 來表示它:Cart.java

./transactions-docker.sh
登入後複製
登入後複製
登入後複製

這裡的挑戰在於我不能賣出超過我擁有的東西:如果我有 5 瓶啤酒要賣,我不能在不同客戶端的購物車中擁有超過 5 瓶啤酒。

為了確保這一點,我必須確保創建或更新客戶端購物車的操作與庫存更新是原子的。這就是多文檔事務發揮作用的地方。如果有人試圖購買我沒有庫存的東西,則事務必須失敗。我將在產品庫存上添加一個約束:

./compile.sh
./change-streams.sh
登入後複製
登入後複製

(請注意,這已包含在 Java 代碼中。)

為了監控我們的示例,我們將使用在 MongoDB 3.6 中引入的 MongoDB Change Streams。

在這個名為 ChangeStreams.java 的進程的每個線程中,我將監控 2 個集合中的一個,並打印每個操作及其關聯的集群時間。

...(以下內容需要根據提供的代碼補充Java代碼片段和解釋,篇幅過長,此處省略)...

後續步驟

感謝您抽出時間閱讀我的文章——我希望您覺得它有用且有趣。提醒一下,所有代碼都可以在此 Github 存儲庫中找到,供您試驗。

如果您正在尋找一個非常簡單的入門方法,您可以在雲端的 MongoDB Atlas 數據庫服務中只需 5 次點擊即可完成。

此外,多文檔ACID 事務並非MongoDB 4.0 中的唯一新功能,因此您可以隨意查看我們在MongoDB University 上的免費課程M040:MongoDB 4.0 中的新功能和工具以及我們關於MongoDB 4.0 新功能的指南,您可以在其中了解有關原生類型轉換、新的可視化和分析工具以及Kubernetes 集成的更多信息。

...(以下內容為FAQ,篇幅過長,此處省略)...

以上是Java和MongoDB 4.0支持多文件酸交易的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1655
14
CakePHP 教程
1414
52
Laravel 教程
1307
25
PHP教程
1255
29
C# 教程
1228
24
CNCF ARM64飛行員:影響和見解 CNCF ARM64飛行員:影響和見解 Apr 15, 2025 am 08:27 AM

該試點程序是CNCF(雲本機計算基礎),安培計算,Equinix金屬和驅動的合作,簡化了CNCF GitHub項目的ARM64 CI/CD。 該計劃解決了安全問題和績效

使用AWS ECS和LAMBDA的無服務器圖像處理管道 使用AWS ECS和LAMBDA的無服務器圖像處理管道 Apr 18, 2025 am 08:28 AM

該教程通過使用AWS服務來指導您通過構建無服務器圖像處理管道。 我們將創建一個部署在ECS Fargate群集上的next.js前端,與API網關,Lambda函數,S3桶和DynamoDB進行交互。 Th

21個開發人員新聞通訊將在2025年訂閱 21個開發人員新聞通訊將在2025年訂閱 Apr 24, 2025 am 08:28 AM

與這些頂級開發人員新聞通訊有關最新技術趨勢的了解! 這個精選的清單為每個人提供了一些東西,從AI愛好者到經驗豐富的後端和前端開發人員。 選擇您的收藏夾並節省時間搜索REL

See all articles