1. 程式人生 > >MongoDB實戰-生產環境中分片的部署與配置

MongoDB實戰-生產環境中分片的部署與配置

    在生產環境裡部署分片叢集時,面前會出現很多選擇和挑戰。下面會介紹幾個推薦的拓撲結構。

1.部署拓撲

    要執行示例MongoDB分片叢集,你一共要啟動九個程序(每個副本集三個mongod,外加三個配置伺服器)。咋一看,這個數字有點嚇人。一開始使用者會假設在生產環境裡執行兩個分片叢集要有九臺獨立的機器。幸運的是,實際需要的機器要少很多,看一下叢集中各元件所要求的資源就知道為什麼了。

   首先考慮下副本集,每個成員都包含分片的完整資料副本,可能是主節點,也可能是從節點。這些程序總是要求有足夠的磁碟空間來儲存資料,要有足夠的記憶體高效得提供服務。因此,複製mongod是分片叢集中最資源密集型的程序,必須佔有獨立的機器。

   那副本集的仲裁節點呢?這些程序值儲存副本集的配置資料,這些資料就放在一個文件裡。所以,仲裁節點的開銷最小,當然也就不需要自己的伺服器了。

   接下來是配置伺服器,它們同樣只儲存相對較少的資料。舉例來說,配置伺服器上管理示例副本集的資料一共也就大約30KB。如果假設這些資料會隨著分片叢集的增長而線性增長。那麼1TB的分片叢集可能對對應30MB的資料。也就是說配置伺服器同樣不需要有自己的機器。但是,考慮到配置伺服器所扮演的重要角色,一些使用者更傾向於為他們提供一些機器(或虛擬機器)。

   根據你對副本集合分片叢集的瞭解,可以列出部署分片叢集的最低要求:

(1)副本集的每個成員,無論是完整的副本節點還是仲裁節點,都需要放在不同的機器上;

(2)每個用於複製的副本整合員都需要有自己的機器

(3)副本集的仲裁節點時很輕量級的,和其他程序共用一臺機器就可以了;

(4)配置伺服器也可以選擇與其他程序共用一臺機器,唯一的要求是配置急群眾的所有配置伺服器都必須放在不同的機器上。

       下面我們將運用這些規則,針對示例的量分片叢集,你會看到兩個合理的部署拓撲。第一個拓撲只需要四臺機器,下圖描述了程序的分佈情況


這個配置滿足了剛才所說的所有規則。在每臺機器上占主導地位的是各分片的複製節點。剩下的程序經過了精心的安排,所有的三個配置伺服器和每個副本集的仲裁節點都部署在不同的機器上。說起容錯性,該拓撲能容忍任何一臺機器發生故障。無論哪臺機器發生了故障,叢集都能繼續處理讀寫請求。如果發生故障的機器正好運行了一個配置伺服器,那麼所有的塊拆分和遷移都會暫停。幸運的是,暫停分片操作基本不會影響分片叢集的工作;在損失的機器恢復後,就能進行拆分和遷移了。

     這是兩份片叢集的最小推薦配置。但是,那些要求最高可用性和最快恢復途徑的應用程式需要一些更強健的東西。正如前面所述,包含兩個副本集合一個仲裁節點的副本集在恢復的是很脆弱的。如果有三個節點,就能降低恢復時的脆弱程度,還能讓你在從資料中心裡部署一個節點,用於災難恢復。下圖是一個強壯的兩分片叢集拓撲。每個分片都包含三節點的副本集,每個節點都包含完整的資料副本。為了進行災難恢復,從每個分片中抽一個節點,加上一個配置伺服器,部署在從資料中心:要保證那些節點不會成為主節點,可以將它們的優先順序設定為0


     用了這個配置,每個分片會被複制兩次,非僅一次。此外,當主資料中心發生故障時,從資料中心擁有重建分片叢集所需的全部資料。哪種分片拓撲最適合你的應用程式,這種決策總是基於一系列與你能容忍的停機時間有關的考慮。比如根據MTR(Mean Time To Recovery,平均恢復時間)進行評估。考慮潛在的故障場景,並模擬它們。如果一個數據中心發生故障,考慮一下它對應用程式的影響。

2. 配置注意事項

   下面是一些與配置分片叢集相關的注意事項:
(1)估計叢集大小

     使用者經常想知道要部署多少個分片,每個分片應該有多大。當然這個問題的答案取決於所在的環境。如果是部署在亞馬遜的EC2上,在超過最大的刻印例項前都不應該進行分片。如果執行在自己的硬體上,你還可以擁有更大的機器,在資料達到100GB之前都不進行分片,這是很合理的。

   當然,每增加一個分片都會引入額外的複雜性,每個分片都要求進行復制。所以說,少數大分片比大量小分片更好。

(2)對現有集合進行分片

    你可以對現有集合進行分片,如果花了很多時間才將資料分佈到各分片裡,請不要大驚小怪的。每次只能做一輪均衡,遷移過程中每分鐘只能移動大約100-200MB資料。因此,對一個50GB的集合進行分片大約需要八個小時,其中還可能牽涉到一定的磁碟活動。此外,在對這樣大集合進行初始分片時,可能還要手動拆分以加速分片過程,因為拆分時由插入觸發的。

   說到這裡,應該已經很清楚了,在最後時候對一個集合進行分片並不是處理效能問題的好辦法。如果你計劃在未來某個時刻對集合進行分片,考慮到可以預見的效能下降,應該提前分片。

(3)在初始載入時預拆分塊

    如果你有一個很大的資料集需要載入到分片集合裡,並且知道資料分佈的規律,那麼可以通過對塊的預拆分和預遷移節省很多時間。舉個例子,假設你想要把電子表格匯入到一個新的MongoDB分片叢集裡。可以在匯入時先拆分塊,隨後將它們遷移到分片裡,藉此保證資料是均勻分佈的。你能用split和moveChunk命令實現這個目標,它們的輔助方法分別是sh.splitAt()和sh.moveChunks().

    下面是一個手動拆分的例子,你發出的split命令,指定你想要的集合,隨後指明拆分點:

sh.splitAt("cloud-docs.spreadsheets",{"username":"Chen","_id":ObjectId("4d6b59db1d1c8536f001453")})
    命令執行時會定位到某個塊,而這個塊邏輯上包含username是Chen並且_id是對應ObjectId的文件。該命令隨後會根據這個點來拆分塊,最後得到兩個塊。你能像這樣繼續拆分,知道擁有資料良好分佈的塊集合。你還要確保建立足夠數量的塊,讓平均塊大小保持在64MB的拆分閾值以內。所以,如果要載入1GB的資料,應該計劃建立大約20個塊。

    第二步是確定所有分片都擁有數量相當的塊。因為所有的塊最初都在一個分片上,你需要移動它們。可以使用moveChunk命令來移動塊,比如下面的語句的含義是將包含文件{username:"Chen"}的塊遷移到分片B上。

sh.moveChunk("cloud-docs.spreadsheets",{username:"Chen"},"shardB")