MongoDB Sharding(一) -- 分片的概念

(一)分片的由來
隨着系統的業務量越來越大,業務系統往往會出現這樣一些特點:

  • 高吞吐量
  • 高併發
  • 超大規模的數據量

高併發的業務可能會耗盡服務器的CPU,高吞吐量、超大規模的數據量也會帶來內存、磁盤的壓力。

對於這類問題,解決系統增長的方法有2種:垂直擴展和水平擴展。

  • 垂直擴展主要是增加單個服務器的資源。例如:使用增強大的CPU、增加更多的內存、使用固態硬盤等。
  • 水平擴展主要是增加服務器。雖然單臺服務器的整體速度或者容量都比較低,但如果每臺服務器只處理工作量的一部分,則與單臺服務器相比,可以提供更多的資源,提高效率。

垂直擴展終歸有一個上限,例如,我已經用了最好的CPU、服務器主板也已經插滿了內存、也使用了SSD存儲設備,可是依然還是無法滿足需求。那麼這個時候就不得不考慮使用水平擴展了,通過增加機器,將業務、數據拆分到不同的機器上,實現業務的分流。

MongoDB是如何實現水平擴展的呢?Sharding,中文即分片。分片是指將數據拆分,將其分散放在不同主機上的過程。

 

(二)何時分片
如果在系統建設初期,就能夠較爲準確的評估出將來的業務量,那麼直接在建設系統時就實施分片是最好的。但是在實際應用中,我們很難評估出將來的業務量大小,所以最好是在業務運行一段時間之後進行分片,當然,也不能在業務運行了幾乎達到滿負載運行時才進行分片,因爲在近乎滿負載的集羣上不停機進行分片是非常困難的。通常,分片用來:

  • 增加可用RAM
  • 增加可用磁盤空間
  • 減輕單臺服務器的負載
  • 處理單臺服務器無法處理的吞吐量

 

(三)分片集羣架構
一個完整的分片集羣的架構如下圖

其核心主要包括:mongos、config server、shard三部分。

 

(3.1)mongos
mongos是查詢路由,在客戶端程序和分片之間提供接口,用戶如果要訪問mongodb分片數據庫,必須使用mongos。部署多個mongos可支持高可用性和可拓展性,一個常見的模式是在每個應用服務器上部署一個mongos,以減少應用程序和mongos之間的網絡延遲。
mongos從配置服務器讀取分片集羣元數據並緩存下來,利用元數據,實現對客戶端讀寫操作的路由。

(3.1.1)mongos如何處理查詢修飾符

 sort    :如果查詢語句不包含排序,則mongos實例將打開結果遊標,對該遊標分片上的所有遊標進行輪詢。
 limit   :如果使用limit限制了結果集大小,則mongos會將limit操作下發到分片上,然後再將limit操作用於分片返回的結果。
 skip     :如果查詢中使用了skip,則不能將skip傳給分片,而是從分片檢索未跳過的結果,並將組裝完結果後跳過指定的文檔數量

(3.1.2)確認與mongos實例的連接
要檢測客戶端是否連接到mongos,使用isMaster命令,當連接到mongos時,會返回"msg" : "isdbgrid"。

db.isMaster()

/* 1 */
{
    "ismaster" : true,
    "msg" : "isdbgrid",
    "maxBsonObjectSize" : 16777216,
    "maxMessageSizeBytes" : 48000000,
    "maxWriteBatchSize" : 100000,
    "localTime" : ISODate("2021-01-15T07:00:23.585Z"),
    "logicalSessionTimeoutMinutes" : 30,
    "connectionId" : 42,
    "maxWireVersion" : 8,
    "minWireVersion" : 0,
    "ok" : 1.0,
    "operationTime" : Timestamp(1610694017, 2),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1610694017, 2),
        "signature" : {
            "hash" : { "$binary" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "$type" : "00" },
            "keyId" : NumberLong(0)
        }
    }
}

(3.1.3)目標操作和廣播操作
在分片集羣中,最快的操作是使用mongos通過shard key路由到單個分片上,這種目標操作使用shard key定位滿足查詢的文檔分片或分片子集。對於不包含分片鍵的查詢,mongos必須查詢所有的分片,然後將結果返回給客戶端,這些“scatter/gather”查詢可能會消耗更多的時間。

(3.1.4)元數據操作
mongos使用"majority"寫關注操作元數據:

命令                               方法    
-------------                    ----------------
addShard                           sh.addShard()     
create                             db.createCollection()     
drop                               db.collection.drop()     
dropDatabase                       db.dropDatabase()    
enableSharding                     sh.enableSharding()     
movePrimary          
renameCollection                   db.collection.renameCollection()     
shardCollection                    sh.shardCollection()     
removeShard          
setFeatureCompatibilityVersion          

 (3.1.5)FCV兼容性

從MongoDB 4.0開始,mongos嘗試連接mongod實例時,如果mongos功能兼容版本(feature compatibility version,fcv)小於mongod,則會造成mongos的二進制文件崩潰。例如:

  • 不能使用fcv是4.0版本的mongos連接到fcv是4.2版本的分片集羣
  • 可以使用fcv是4.2版本的mongos連接到fcv是4.0版本的分片集羣

 

 (3.2)config server

配置服務器存儲集羣的元數據,元數據反映分片集羣的內所有數據和組件的狀態和組織方式,元數據包含每個分片上的塊列表以及定義塊的範圍。從3.4版本開始,已棄用鏡像服務器用作配置服務器(SCCC),config Server必須部署爲副本集架構(CSRS)。

Mongos實例緩存配置服務器的數據,並使用它路由讀和寫操作到正確的分片。當元數據發生改變的時候(例如:添加新的分片、chunks分裂),mongos更新緩存數據。此外,配置服務器還存儲基於角色的用戶權限信息。MongoDB也是用配置服務器管理分佈式鎖。每個分片集羣都必須有自己的配置服務器,不能共享同一個配置服務器,配置服務器必須運行在WiredTiger存儲。

(3.2.1)配置服務器的讀寫操作
在配置服務器上存在admin和config數據庫,admin數據庫包含身份驗證以及授權相關的集合及其它的system.*集合,config數據庫包含分片集羣元數據的集合,當元數據發生變更時,MongoDB會將數據寫入到config服務器。在做操作或者維護期間,我們應該避免直接去寫配置服務器。當我們從副本集配置服務器讀數據時,MongoDB使用”majority”讀關注,以避免幻讀;當我們從副本集配置服務器寫數據時,MongoDB使用”majority”寫關注,以確保數據不會丟失。

(3.2.2)配置服務器可用性
如果配置副本集丟失其主服務器並且無法選舉主節點,則集羣元數據變爲只讀,此時仍然可以從集羣中讀和寫數據,但是不能夠執行chunk合併、分裂等改變元數據的操作。
如果所有的副本集服務器不可用,集羣將變得不可用。爲了確保配置服務器保持可用和完整,備份就顯得十分重要,配置服務器數據量很小,備份對主機的性能影響也相對較小。

(3.3.3)分片集羣的元數據
分片集羣的元數據存儲在配置服務器的config數據庫中。通常,永遠不要直接編輯config數據庫的內容,config數據庫包含以下集合:

use config

show collections
------------------------------
actionlog
changelog
chunks
collections
databases
lockpings
locks
migrations
mongos
shards
system.sessions
tags
transactions
version

 

(3.3)Shard
shard是存儲數據的地方,每個shard包含集合的一部分數據,從3.6版本開始,每個shard必須部署爲副本集(replica set)架構。

(3.3.1)主分片的概念

分片集羣中的每個數據庫都有一個主分片,其中包含該數據庫所有未分片的集合。當在分片集羣中創建一個新的數據庫時,mongos會爲新數據庫選擇一個分片作爲主分片。選擇的機制爲:選擇數據量少的分片作爲新數據庫的主分片。如下圖:集羣存在2個分片,對於Collection2集合,沒有實施分片,則將全部數據存放在其主分片上。

特別注意:
主分片與副本集的主節點沒有任何關係。

 

 

 

 【完】

 

相關文檔合集:

1. MongoDB Sharding(一) -- 分片的概念
2. MongoDB Sharding(二) -- 搭建分片集羣
3. MongoDB Sharding(三) -- zone
4. MongoDB Sharding(四) -- 分片集羣的維護管理

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章