MongoDB 主從複製 - Windows 或 Linux
我最近將我的 MS SQL Server 數據庫移至 Windows Server 2008 上的 MongoDB (2.0)。它包含 2 個具有以下統計資訊的數據庫。(兩個數據庫每秒大約有 100 次讀取/寫入)。這些寫入由執行在同一數據庫伺服器上的 .Net 應用程序執行。
> db.stats() { "db" : "FirstDB", "collections" : 112, "objects" : 94020788, "avgObjSize" : 62.86065307174409, "dataSize" : 5910208136, "storageSize" : 14340792320, "numExtents" : 1277, "indexes" : 110, "indexSize" : 4279800784, "fileSize" : 27837595648, "nsSizeMB" : 16, "ok" : 1 } > db.stats() { "db" : "SecondDB", "collections" : 10, "objects" : 2926198, "avgObjSize" : 158.5025346883567, "dataSize" : 463809800, "storageSize" : 720027648, "numExtents" : 49, "indexes" : 8, "indexSize" : 115248896, "fileSize" : 2080374784, "nsSizeMB" : 16, "ok" : 1 }
我發現 MongoDB 可以以所需的讀/寫速度保存我的所有數據。現在我需要專家幫助來加強我的單伺服器(數據庫+應用程序)設置的可靠性;
但是,在 1 個月的時間裡,我遇到了以下 MongoDB-On-Windows 問題;
- 由於收集損壞而導致意外關閉
- MongoDB 沒有為已刪除的對象釋放磁碟空間(目前大約 28 GB 並且還在增長)
- 頁面錯誤數量增加
- 無法控制 RAM 中的數據(無法在 RAM 中預載入所需數據並在幾分鐘後刪除)
- 常見的數據庫錯誤,例如:無法從傳輸連接中讀取數據…
對我來說,可靠性/備份/性能的最佳救援設置是什麼?
- 將 MongoDB 遷移到 Linux(前提是我使用此數據庫的 .Net 應用程序將駐留在同一 LAN 內的 Windows Server 上)?要麼
- 使用 Windows 上的 Master 和 Linux 上的 Slave 設置 2 台伺服器副本集?要麼
- 你建議什麼…?
編輯-1:
> db.serverStatus() { "host" : "OWNEROR-GTPD0H9", "version" : "2.2.2", "process" : "mongod", "pid" : 5972, "uptime" : 2246315, "uptimeMillis" : NumberLong("2246314871"), "uptimeEstimate" : 1418073, "localTime" : ISODate("2013-02-01T18:20:48.371Z"), "locks" : { "." : { "timeLockedMicros" : { "R" : NumberLong(1009609910), "W" : NumberLong("41166641284") }, "timeAcquiringMicros" : { "R" : NumberLong("233444382285"), "W" : NumberLong("26675293061") } }, "admin" : { "timeLockedMicros" : { "r" : NumberLong("20598738435"), "w" : NumberLong(0) }, "timeAcquiringMicros" : { "r" : NumberLong("681905051780"), "w" : NumberLong(0) } }, "local" : { "timeLockedMicros" : { "r" : NumberLong(7054206), "w" : NumberLong(0) }, "timeAcquiringMicros" : { "r" : NumberLong(323140436), "w" : NumberLong(0) } }, "FirstDB" : { "timeLockedMicros" : { "r" : NumberLong("40372661580"), "w" : NumberLong("54059509747") }, "timeAcquiringMicros" : { "r" : NumberLong("769458843030"), "w" : NumberLong("357708107433") } }, "SecondDB" : { "timeLockedMicros" : { "r" : NumberLong("25053503869"), "w" : NumberLong("395081595504") }, "timeAcquiringMicros" : { "r" : NumberLong("69429086729"), "w" : NumberLong("9163194312205") } } }, "globalLock" : { "totalTime" : NumberLong("2246314871000"), "lockTime" : NumberLong("41166641284"), "currentQueue" : { "total" : 54, "readers" : 52, "writers" : 2 }, "activeClients" : { "total" : 2, "readers" : 0, "writers" : 2 } }, "mem" : { "bits" : 64, "resident" : 69, "virtual" : 34059, "supported" : true, "mapped" : 16793, "mappedWithJournal" : 33586 }, "connections" : { "current" : 114, "available" : 19886 }, "extra_info" : { "note" : "fields vary by platform", "page_faults" : 631285910, "usagePageFileMB" : 6848, "totalPageFileMB" : 49132, "availPageFileMB" : 34274, "ramMB" : 24567 }, "indexCounters" : { "note" : "not supported on this platform" }, "backgroundFlushing" : { "flushes" : 37430, "total_ms" : 86130745, "average_ms" : 2301.115281859471, "last_ms" : 3853, "last_finished" : ISODate("2013-02-01T18:19:49.233Z") }, "cursors" : { "totalOpen" : 227, "clientCursors_size" : 227, "timedOut" : 125, "totalNoTimeout" : 226 }, "network" : { "bytesIn" : 46807928165, "bytesOut" : 24400717839, "numRequests" : 462799358 }, "opcounters" : { "insert" : 92590009, "query" : 92755757, "update" : 183285338, "delete" : 7489, "getmore" : 1004, "command" : 94208472 }, "asserts" : { "regular" : 0, "warning" : 0, "msg" : 0, "user" : 97431, "rollovers" : 0 }, "writeBacksQueued" : false, "dur" : { "commits" : 17, "journaledMB" : 0.139264, "writeToDataFilesMB" : 0.033338, "compression" : 2.2571516556184057, "commitsInWriteLock" : 0, "earlyCommits" : 0, "timeMs" : { "dt" : 3291, "prepLogBuffer" : 0, "writeToJournal" : 8, "writeToDataFiles" : 1, "remapPrivateView" : 38 } }, "recordStats" : { "accessesNotInMemory" : 3942359, "pageFaultExceptionsThrown" : 15956, "FirstDB" : { "accessesNotInMemory" : 163718, "pageFaultExceptionsThrown" : 6931 }, "SecondDB" : { "accessesNotInMemory" : 3778641, "pageFaultExceptionsThrown" : 9025 }, "admin" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 }, "local" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 } }, "ok" : 1 }
這是一個相當複雜的問題,但我將對每個問題進行簡要回答。您應該嘗試這些,然後問一個更具體的問題(例如,提供有關 RAM 可用性和使用率的詳細資訊,以及用於診斷頁面錯誤的工作數據集大小)。
由於收集損壞而導致意外關閉
您沒有列出完整版本,但請確保您至少使用 2.0 的更高版本,最好是 2.2(在撰寫本文時,2.2.3 處於候選發布狀態)。後來在 2.0 分支中有多個與 Windows 相關的修復,其中一些修復了使 Windows 建構不易受到硬崩潰(這可能導致損壞)的問題。
MongoDB 沒有為已刪除的對象釋放磁碟空間(目前大約 28 GB 並且還在增長)
這已在許多其他文章和討論中有所涉及 - 請在此處查看我的答案:
https://stackoverflow.com/questions/13390160/does-mongodb-reuse-deleted-space
頁面錯誤數量增加無法控制 RAM 中的數據(無法在 RAM 中預載入所需數據並在幾分鐘後刪除)
如上所述,頁面錯誤和數據適合 RAM 需要更多詳細資訊 - 你有多少數據,你的工作集大小是多少,你的索引是否適合記憶體等。在 mongodb-user Google group 上也有很多討論以及有關此問題的 Stack Overflow 以及如何在MMS中跟踪此問題- 在您送出新問題之前,建議您在此處搜尋一些常用方法。您還應該注意,由於作業系統報告“軟”頁面錯誤(已經在記憶體中但未被程序擁有/觸及)和“硬”頁面錯誤(實際上是從磁碟分頁),Windows 中的頁面錯誤報告可能很難解釋以幾乎相同的方式。
關於預載入的說明,您可以使用 2.2+ 中的touch 命令執行此操作,用於索引、數據或兩者(請參閱連結頁面以獲取選項)。
常見的數據庫錯誤,例如:無法從傳輸連接中讀取數據…
同樣,這將需要日誌、系統上的相對負載的概念等。肯定需要更多細節 - 您可能只是遇到超時或類似情況,因為您正在超載數據庫。如果在您解決其他問題後這些錯誤仍然存在,我會建議一個單獨的問題
將 MongoDB 移動到 Linux(前提是我使用此數據庫的 .Net 應用程序將駐留在同一 LAN 內的 Windows Server 上)?
與 Windows 相比,在 Linux 上使用 MongoDB 的人更多,因此該平台上的社區對其進行了更廣泛的測試和使用,但在 Windows 和大型安裝中使用量很大。移動作業系統不一定會解決或自動修復問題。如果您的數據在 Windows 上不適合 RAM,例如,它可能也不適合在 Linux 上,也不會改變 MongoDB 重用已刪除空間的方式。
使用 Windows 上的 Master 和 Linux 上的 Slave 設置 2 台伺服器副本集?要麼
無論作業系統如何,您都應該始終執行副本集(最少的主要、從屬、仲裁者)。一般來說,這只是一個好主意,但特別是如果您看到您描述的一些問題。雖然理論上您可以像您提到的那樣混合作業系統,但我建議您選擇其中一個並使用它。
亞當已經涵蓋了大部分要點。但是,有幾件事要補充。
在生產環境中使用 Windows
對於 tl;dr 候選人:執行 mongod 實例(Windows 上的配置伺服器除外)是一個非常糟糕的主意™。
這就是為什麼。
- ReFS 和 NTFS 都至少比 ext4 或 XFS(推薦用於 Linux 生產環境的文件系統)慢 1/3。有關詳細資訊,請參閱關於 slideshare 的詳細比較。
- Windows 中的記憶體管理通常不適用於 MongoDB。Windows 盡可能多地使用它的頁面文件,從而使操作成為文件操作,而在 Linux 上它們將成為 RAM 操作。後者要快幾個數量級,最高可達 40,000 (40k) 倍。這很容易加起來。
- 對數據庫來說絕對沒用的作業系統 GUI 會佔用 RAM。
由於配置伺服器通常不像數據承載節點那樣看到那麼多動作,它可以在 Windows 上執行。
數據預熱
該
touch
命令很有用,將使預熱變得非常容易。但是,它不是很精細。從 mongo shell 中使用 an 進行典型查詢.hint({<yourIndicesHere>).explain()
不僅會將選定的索引載入到 RAM 中,而且還會找到該查詢的最佳查詢計劃,該計劃將一直保存到對集合進行 1000 次寫入操作之後,然後再重新評估它。執行具有混合作業系統的副本集
雖然這通常是可能的,但這是另一個非常糟糕的主意™。由於 mongod 在 Windows 上的性能下降,很可能遲早會遇到稱為複制滯後的問題,如果滯後超過 oplog 長度,基本上會迫使您重新同步滯後的成員,從而帶走非常想要的重新同步時的冗餘。如果重新同步花費的時間超過了 oplog 長度可以橋接的時間,那麼對於所有實際目的,該節點都已失效。有一些方法可以處理複製滯後(例如,通過相應地設置寫入關注點),但從長遠來看,在不同作業系統上執行副本集的成員是解決問題的好方法。總而言之,我贊同 Adam 的建議,即不要在複製環境中混合作業系統。