我知道這裏有類似的問題,但他們要麼telling me到如果我需要交易切換回常規的RDBMS系統或使用atomic operations或two-phase commit。第二種解決方案似乎是最佳選擇。第三個我不想跟隨,因爲看起來很多事情可能會出錯,我無法在各個方面進行測試。我很難重構我的項目來執行原子操作。我不知道這是否來自我有限的觀點(迄今爲止我只使用過SQL數據庫),或者它是否實際上無法完成。如何解決MongoDB中缺少事務的問題?
我們想在我們公司進行試點測試的MongoDB。我們選擇了一個相對簡單的項目 - 一個短信網關。它允許我們的軟件發送SMS消息到蜂窩網絡,網關完成骯髒的工作:實際上通過不同的通信協議與提供商進行通信。網關還管理消息的計費。每個申請該服務的客戶都必須購買一些信用。系統在發送消息時自動減少用戶的餘額,如果餘額不足,則拒絕訪問。同樣因爲我們是第三方短信服務提供商的客戶,我們也可能與他們有自己的餘額。我們也必須跟蹤這些。
我開始思考我如何可以將需要的數據存儲與MongoDB中,如果我砍倒了一些複雜性(外部計費,排隊短信發送)。從SQL世界來,我就會爲用戶創建一個單獨的表,另一個用於短信,以及一個用於存儲有關用戶的餘額交易。假設我爲MongoDB中的所有人創建了單獨的集合。
想象短信在這個簡化的系統下面的步驟發送任務:
檢查用戶是否有足夠的餘額;拒絕訪問,如果沒有足夠的信用
發送和存儲消息在SMS收集中的細節和成本(在現場系統中,消息將具有
status
屬性,並且任務將拾取它用於遞送並設置根據其當前狀態)下降短信的價格用戶的平衡被髮送的消息
日誌交易收集
現在有什麼問題呢? MongoDB只能在一個文檔上進行原子更新。在之前的流程中,可能會發生某種錯誤,並且消息會存儲在數據庫中,但用戶的餘額不會更新和/或事務未記錄。
我想出了兩個想法:
爲用戶創建一個單一的集合,並存儲餘額作爲一個字段,用戶關聯交易和信息爲用戶的文檔中的子文檔。因爲我們可以自動更新文件,所以這實際上解決了交易問題。缺點:如果用戶發送很多短信,文檔的大小可能會變大,並且可能會達到4MB的文檔限制。也許我可以在這種情況下創建歷史文檔,但我認爲這不是一個好主意。另外我不知道如果我將越來越多的數據推送到同一個大文檔,系統會有多快。
爲用戶創造一個集合,一個用於交易。可以有兩種交易:信用卡購買與正結餘變化和信息發送負平衡變化。交易可能有一個子文件;例如在消息發送 SMS的細節可以嵌入到交易中。缺點:我不存儲當前的用戶餘額,所以每次用戶嘗試發送消息以告知消息是否可以通過時,我都必須計算它。恐怕這個計算會隨着存儲事務數量的增長而變慢。
我有點困惑要選擇哪種方法。還有其他解決方案嗎?我無法在網上找到任何關於如何解決這些問題的最佳實踐。我想很多試圖熟悉NoSQL世界的程序員在開始時都面臨類似的問題。
原諒我,如果我錯了,但看起來好像這個項目將使用NoSQL數據存儲,無論它是否會從中受益。 NoSQL不是SQL的替代選擇,而是一種「時尚」選擇,但是當關系型RDBMS的技術不適合問題空間和非關係型數據存儲時。很多你的問題有「如果它是SQL,那麼......」並且對我發出警告。所有NoSQL都來自需要解決SQL無法解決的問題,然後將它們推廣到易於使用的階段,然後當然這一潮流開始滾動。 – PurplePilot
我知道這個項目並不是嘗試使用NoSQL的最佳選擇。然而,如果我們開始將其用於其他項目(比如說圖書館館藏管理軟件,因爲我們正在進行館藏管理),並且突然出現某種請求需要交易(並且實際上存在這種請求,那麼想象一本書從一個集合轉移到另一個集合),我們需要知道我們如何克服這個問題。也許這只是我狹隘的思想,認爲總是需要交易。但它可能是有辦法克服這些不知何故。 – NagyI
我同意PurplePilot,你應該選擇一種適合解決方案的技術,而不是嘗試移植一個不適合解決問題的解決方案。爲圖形數據庫建模數據是與RDBMS設計完全不同的範例,你必須忘記你所知道的一切,重新學習新的思維方式。 –