2013-10-20 114 views
1

我有一個node.js應用程序,在一週內將生產mongodb後端,我對如何處理應用程序崩潰和重新啓動有一些疑問。Node.js(&MongoDB)服務器崩潰,數據庫操作一半?

說我有一個簡單的路線/followUser中,我有2個數據庫操作

/followUser 
----->Update User1 Document.followers = User2 
----->Update User2 Document.followers = User1 
----->Some other mongodb(via mongoose)operation 

,如果有一臺服務器崩潰,會發生什麼(由於電源故障或可能的遠程MongoDB的服務器關閉)這樣的場景:

----->Update User1 Document.followers = User2 
SERVER CRASHED , FOREVER RESTARTS NODE 

以下操作會發生什麼?該系統目前正處於不一致的狀態,我可能有錯誤,每次我要求用戶2追隨者

----->Update User2 Document.followers = User1 
----->Some other mongodb(via mongoose)operation 

也請推薦優秀的日誌記錄和在Linux上運行的應用程序啓動/顯示器模塊。

現在我正在使用域來捕獲異常,做server.close,但在process.exit()之前我想確保所有的數據庫事務都完成了,我可以通過測試來檢查事件循環是否爲空或者不(如何?)然後process.exit(1)?

回答

3

您需要的交易對於這一點,並且因爲MongoDB的沒有他們在這裏是一種變通方法來解決這個問題是清理代碼添加到您的應用程序運行時應用程序啓動http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/

+1

對於這款TokuMX,您對這款多狀態交易支持的看法如何呢? –

+0

我沒有進入MongoDB內部,但據我所知,不能在沒有任何權衡的情況下實現ACID(請參閱http://en.wikipedia.org/wiki/CAP_theorem)。所以如果你真的需要事務處理,你最好使用DBMS和本地事務處理支持。 – vkurchatkin

+0

^這。MongoDB不支持在多個文檔上進行完整的原子操作。或者你嘗試一些或多或少便宜的解決方法,或者你去RDBMS。 – durum

2

的一種方式。您可以編寫清理代碼對數據的任何部分執行完整性檢查,這些部分可以像您的示例一樣通過多個步驟進行更新,然後以任何對您的應用程序有意義的方式修復該數據。

根據您的應用程序/數據的複雜程度,這可能還需要您記錄應用程序試圖執行的操作的日誌,但這會變得非常複雜。理想情況下,更重要的是刷新非規格化數據和刪除部分數據。

您想在啓動過程中執行此操作而不是關閉操作,因爲不能保證您的關閉代碼將完全運行,並且如果由於異常而關閉,您不知道系統狀態。

+0

現在我實現了domain和im在server.close()之後調用mongoose.connection.close()。但是我聽說如果有任何掛起的數據庫I/O而不是它被忽略,那麼不會調用mongoose close()。我已經把process.exit(1)放在了貓鼬的關閉回調中。這可以嗎 ? –

+0

@RanaDeep調用'mongoose.connection.close()'或'mongoose.disconnect()'會中止任何懸而未決的I/O,並且應該阻止甚至需要調用'process.exit',但是在'close'中調用'回調也可以。 – JohnnyHK

+0

http://stackoverflow.com/questions/8813838/properly-close-mongooses-connection-once-youre-done 在編輯問題時,它說mongoose.connection.close()會被忽略,如果有的話等待I/O,我不知道它的固定在最新版本? –

1

vkurchatkin在this link給出的解決方案是一種解決方法,以防您的應用程序服務器崩潰,因爲您將能夠知道當時哪些事務處於掛起狀態。如果你在你的代碼中實現了這個功能,你可以按照JohnnyHK的建議在系統重新啓動時創建清理代碼。你提到的代碼(捕獲異常,在關閉時測試等)將無法正常工作,因爲...呃...你的服務器崩潰了! ;-)

這就是說,這是使用數據庫完成的,因此您必須保證數據庫不會崩潰。我建議你使用replication。它基本上是一個服務器集羣,如果一個節點發生故障,它可以自我恢復,並且您還可以進行一些檢查以確保數據到達服務器並且是安全的。

希望這會有所幫助。

+0

複製不能保證你的數據庫不會崩潰!實際上,副本集的存在是因爲它可以保證你的服務器遲早會崩潰! :) –

+0

@Asya Kamsky - 我明白你的觀點,服務器遲早會崩潰。事實上,正如你指出的那樣,這就是爲什麼我建議複製集。數據庫服務器將會崩潰,但是如果您的複製活動,數據庫仍然可以工作,恢復將自動完成(如果主服務器是主服務器崩潰的主服務器,並且如果它是輔助服務器,則會選擇一個新的主服務器,發生)。當然,我正在談論不同服務器中的副本集(否則這是毫無意義的!)。我建議遵循vkurchatkin方法來應用程序崩潰**加**副本集。 – Moreno