2011-08-11 39 views
14

我正在研究一個有一些重要數據的項目。這意味着如果燈光或服務器出現故障,我們不能丟失任何信息。我們使用MongoDB作爲數據庫。如果沒有插入一個元素,我想確保在插入並回滾整個批處理後,我的數據位於數據庫中。我知道這是Mongo背後的哲學,我們不需要交易,但我如何確保我的數據在插入後真正安全地存儲,而不是發送到某個「黑洞」。MongoDB的安全模式對插入有多安全?

  • 我應該搜索嗎?

  • 我應該使用一些特定的mongoDB命令嗎?

  • 我應該使用分片即使一臺服務器用於滿足
    的速度和如果光
    下山它並不能保證任何事情的方式是不夠嗎?

什麼是最佳解決方案?

回答

14

最好的辦法是用寫的擔憂 - 這允許你告訴MongoDB中多麼重要的一塊數據是。最快的Write Writen也是最不安全的 - 在下一次預定的刷新之前,數據不會刷新到磁盤。最安全的將確認數據在返回之前已經被寫入到多個機器上的磁盤上。

您正在尋找的寫入問題是FSYNC_SAFE(至少這是從Java driver的角度調用的)或REPLICAS_SAFE,它確認您的數據已被複制。

記住,MongoDB中沒有傳統意義上的交易 - 你的回退將不得不用手卷起因爲你不能告訴Mongo的數據庫來爲你做這個。

您需要做的另一件事是使用相對較新的--journal選項(使用Write Ahead Log),或使用副本集在多臺機器上共享數據,以便在發生崩潰/電力損失。

分片並不是一個防止硬件故障的方法,因爲在處理特別大的數據集時共享負載的方法 - 分片不應該與副本集混淆,這是一種將數據寫入多個磁盤的方式多臺機器。

因此,如果您的數據足夠有價值,那麼您肯定應該使用副本集,甚至可能在其他數據中心/可用性區/機架等中安裝從屬設備,以提供您所需的彈性。

有一個方法可以指出副本集中各個節點的優先級,這樣,如果主服務器出現故障,那麼當選的新主服務器就是一個如果這樣一臺機器可以在同一個數據中心(即成爲主停止在該國的另一側的奴隸,除非它真的是唯一的選擇)。

+0

非常感謝您的回覆。我會等待一段時間的其他回覆,如果我沒有發現任何新內容,我會接受它,謝謝 –

+0

tl; dr:你搞砸了! – Mrchief

5

我收到一個非常好的答案,來自一個叫做GVP的人。我將引用它(基本上它加起來豐富的答案):

我想確保我的數據是在 插入之後,數據庫和回滾整批如果一個元素沒有被插入。

這是一個複雜的話題,有幾個權衡,你必須 在這裏考慮。

我應該使用分片嗎?

分片用於縮放寫入。爲了數據安全,您需要查看 副本集。

我應該使用一些特定的mongoDB命令嗎?

首先要考慮的是「安全」模式或「getLastError()」,由Andreas指示爲 。如果發出「安全」寫入,則知道數據庫已收到插入並應用寫入。但是, MongoDB每60秒只刷新一次磁盤,所以服務器可能會在沒有磁盤上的數據的情況下失敗 。

要考慮的第二件事是「日記」 (v1.8 +)。打開日記功能後,數據每100毫秒刷新到日誌 。所以你在失敗之前有一個較小的時間窗口。 驅動程序有一個「fsync」選項(檢查該名稱)比「安全」更進一步 ,它會等待確認數據已將 刷新到磁盤(即日誌文件)。但是,這隻有 涵蓋一臺服務器。如果服務器上的硬盤驅動器 死機會發生什麼情況?那麼你需要第二個副本。

要考慮的第三件事是 複製。在返回之前,驅動程序支持一個「W」參數,該參數表示「將這些數據複製到N個節點」。如果在某個超時之前寫入沒有達到「N」個節點,則寫入失敗(拋出異常 )。但是,您必須根據副本集中的 個節點正確配置「W」。同樣,因爲硬盤驅動器 可能會失敗,即使使用日記功能,您也需要查看複製。 然後跨越數據中心進行復制,因此太長而無法將 置於此處。最後要考慮的是你要求「回滾 」。根據我的理解,MongoDB不具備「回滾」容量。如果你正在進行批量插入,你會得到的最好是一個 指示哪些元素失敗。

下面是這個PHP驅動程序的鏈接:http://it.php.net/manual/en/mongocollection.batchinsert.php您必須檢查有關複製和W參數的詳細信息。我相信這裏也適用相同的限制。