跨多個不同地理區域的 Rails/Mongo
我有一個系統,它必然需要在三個或更多不同的位置物理存在,並且我需要有關結構化的建議,以使我的數據庫能夠及時復製而沒有可怕的延遲。當應用程序伺服器試圖與沒有物理配置的節點通信時,我已經看到 mysql 訪問和複製非常慢。在這種情況下,我使用的是 mongodb。
- 堆棧是 linux/passenger/ruby/rails/mongodb。
- 數據庫是寫重讀輕。
- 基礎設施是 Amazon EC2
- 應用層必須在物理上位於 3 個或更多不同的位置。我不能進一步證明這個要求是一個要求。但是,如果可以從其他位置快速寫入數據庫,則該數據庫不必位於多個位置。
從閱讀 mongo 的文件來看,mongo 複製似乎更像是一個候選者,而不是分片 b/c 我的數據儲存區並不大。但是,我沒有看到任何解決伺服器跨遠距離通信速度問題的方法,可能存在高延遲。
您的延遲體驗有些令人擔憂。在我自己對本地快速網路的測試中,我注意到 Mongo 和 MySQL 在延遲方面存在一些差異:
- 對於小項目,MySQL 請求往返時間通常低於 5 毫秒。有時低至 2。
- MongoDB 請求 RTT 大約慢 3 倍,大約 15 毫秒。
MongoDB 時間的一部分是由於 TCP 連接設置時間,其中 MySQL 使用預先存在的(池化)連接。在這兩種情況下,數據庫都沒有被複製或分片,所以這些可以被認為是最好的情況(對於我的網路)。
Mongo 副本集可以在這里為您提供幫助,但前提是您的應用程序能夠容忍鬆散收斂1。為了獲得最大速度,您必須將 mongo 寫入配置為僅在 mongodb 伺服器報告已收到寫入時才返回,並將您的應用伺服器配置為僅使用 AZ-local Mongo 實例。讀取將需要使用 SlaveOK,以便他們可以從該 AZ 本地副本讀取,這將顯示本地寫入以及來自到目前為止已聚合的其他節點的複制寫入。這意味著每個 AZ 對整個數據庫的看法都會略有不同;過去的 X 分鐘只會有局部的變化,但深度的歷史會收斂。
此設置將在應用伺服器和數據庫伺服器之間提供低(相同可用區)延遲。但是,來自應用程序伺服器的數據視圖將根據您的應用程序消費者所訪問的可用區而有所不同。這種架構是否適合您的應用程序只能由您決定。
但是,這樣做有一個非常大的問題:**MongoDB 不支持多主2複製,**所有的寫入都必須到單 Master。
目前 (v2.2) 無法配置 MongoDB 以允許寫入從屬伺服器,因此“寫入繁重”應用程序中的所有寫入都必須轉到副本集的單個主伺服器。您沒有提到讀取延遲是否是一個問題,但如果是,那麼 SlaveOK 讀取將獲取本地 Mongo 副本成員;但與上面不同的是,它可能還沒有收到來自 master 的所有更新,因此在 write-submit 和它顯示本地 slave 之間肯定會有延遲。
Mongo 有幾種不同的寫入類型。一旦 Mongo 伺服器完全接收到寫入,預設返回 OK。下一步是僅在向 Journal 送出寫入時才返回 OK 的模式。並且最偏執的(因此在具有副本的 mongo 中是迄今為止最慢的)僅在指定數量的副本報告寫入在其日誌中時才返回 OK 。預設模式最快,但最後一種模式確保本地副本具有寫入(嚴格一致性)。
如果該主伺服器與應用伺服器不在同一個 AZ 中,那麼即使使用預設的寫入方式,延遲也可能對您來說是不可行的。如果是這種情況,mongo 將無法為您工作,因為您的應用程序現在存在。您將不得不認真考慮如何將您的應用程序更改為對寫入的延遲不敏感,或者使用可以在鬆散收斂的情況下進行多主控的非 Mongo 數據庫。
Mongo 最接近多主配置的是通過分片。如果您的應用伺服器知道他們的地理位置,您可以將地理數據包含到 Mongo Shard-Key 中。然後,當你連接到 MongoS 進行寫入時,所有的寫入都會進入本地分片的副本集。讀取可以輪詢整個數據庫(從非本地分片中讀取時會相應地變慢),因此這將保持一致性。但是,這完全取決於您的分片鍵位置。
1:Loose Convergence,分佈式或複制數據庫達到統一狀態的時間就是收斂時間。鬆散收斂是一個長區間。緊收斂是一個很短的間隔。
2: Multi-master , 一個多於一個副本可以接受寫入的數據庫。可以執行此操作的數據庫範例包括 Active Directory、OpenLDAP 和一些 MySQL 配置。