標籤:變更 list 故障 nec product 索引 否則 mini 儲存
[TOC]
一、簡介
MongoDB目前3大核心優勢:『靈活模式』+ 『高可用性』 + 『可擴充性』,通過json文檔來實現靈活模式,通過複製集來保證高可用,通過Sharded cluster來保證可擴充性。
MongoDB 分區叢集Sharded Cluster通過將資料分散儲存到多個分區(Shard)上來實現高可擴充性。
當MongoDB複製集遇到下面的業務情境時,你就需要考慮使用Sharded cluster
- 儲存容量需求超出單機磁碟容量
- 活躍的資料集超出單機記憶體容量,導致很多請求都要從磁碟讀取資料,影響效能
- 寫IOPS超出單個MongoDB節點的寫服務能力
如所示,Sharding Cluster使得集合的資料可以分散到多個Shard(複製集或者單個Mongod節點)儲存,使得MongoDB具備了橫向擴充(Scale out)的能力,豐富了MongoDB的應用情境。
二、分區叢集
實現分區叢集時,MongoDB 引入 Config Server 來儲存叢集的中繼資料,引入 mongos 作為應用訪問的入口,mongos 從 Config Server 讀取路由資訊,並將請求路由到後端對應的 Shard 上。
Diagram of a sample sharded cluster for production purposes. Contains exactly 3 config servers, 2 or more mongos
query routers, and at least 2 shards. The shards are replica sets.
角色說明
A.資料分區(Shards)
用來儲存資料,保證資料的高可用性和一致性。可以是一個單獨的mongod執行個體,也可以是一個複本集。
在生產環境下Shard一般是一個Replica Set,以防止該資料片的單點故障。所有Shard中有一個PrimaryShard,裡麵包含未進行劃分的資料集合:
B.設定管理員(Config servers)
儲存叢集的中繼資料(metadata),包含各個Shard的路由規則。
C.查詢路由(Query Routers)
Mongos是Sharded cluster的訪問入口,其本身並不持久化資料(Sharded cluster所有的中繼資料都會儲存到Config Server,而使用者的資料則會分散儲存到各個shard)
Mongos啟動後,會從config server載入中繼資料,開始提供服務,將使用者的請求正確路由到對應的Shard
Sharding叢集可以有一個mongos,也可以有多mongos以減輕用戶端請求的壓力。
三、資料分布策略
Sharded cluster支援將單個集合的資料分散儲存在多個shard上,使用者可以指定根據集合內文檔的某個欄位即shard key來分布資料,
目前主要支援2種資料分布的策略,範圍分區(Range based sharding)或hash分區(Hash based sharding)。
範圍分區
Diagram of the shard key value space segmented into smaller ranges or chunks.
如所示,集合根據x欄位來分區,x的取值範圍為[minKey, maxKey](x為整型,這裡的minKey、maxKey為整型的最小值和最大值),將整個取值範圍劃分為多個chunk,每個chunk(通常配置為64MB)包含其中一小段的資料。
Chunk1包含x的取值在[minKey, -75)的所有文檔,而Chunk2包含x取值在[-75, 25)之間的所有文檔... 每個chunk的資料都儲存在同一個Shard上,每個Shard可以儲存很多個chunk,chunk儲存在哪個shard的資訊會儲存在Config server種,mongos也會根據各個shard上的chunk的數量來自動做負載平衡。
範圍分區能很好的滿足『範圍查詢』的需求,比如想查詢x的值在[-30, 10]之間的所有文檔,這時mongos直接能將請求路由到Chunk2,就能查詢出所有合格文檔。
範圍分區的缺點在於,如果shardkey有明顯遞增(或者遞減)趨勢,則新插入的文檔多會分布到同一個chunk,無法擴充寫的能力,比如使用_id作為shard key,而MongoDB自動產生的id高位是時間戳記,是持續遞增的。
HASH分區
Hash分區是根據使用者的shard key計算hash值(64bit整型),根據hash值按照『範圍分區』的策略將文檔分布到不同的chunk。
Diagram of the hashed based segmentation.
Hash分區與範圍分區互補,能將文檔隨機的分散到各個chunk,充分的擴充寫能力,彌補了範圍分區的不足,但不能高效的服務涵蓋範圍查詢,所有的範圍查詢要分發到後端所有的Shard才能找出滿足條件的文檔。
合理的選擇shard key
選擇shard key時,要根據業務的需求及『範圍分區』和『Hash分區』2種方式的優缺點合理選擇,同時還要注意shard key的取值一定要足夠多,否則會出現單個jumbo chunk,即單個chunk非常大並且無法分裂(split);比如某集合儲存使用者的資訊,按照age欄位分區,而age的取值非常有限,必定會導致單個chunk非常大。
四、Mongos訪問模式
所有的請求都由mongos來路由、分發、合并,這些動作對用戶端driver透明,使用者串連mongos就像串連mongod一樣使用。
Mongos會根據請求類型及shard key將請求路由到對應的Shard,因此不同的操作請求存在不同限制。
查詢請求
查詢請求不包含shard key,則必須將查詢分發到所有的shard,然後合并查詢結果返回給用戶端
查詢請求包含shard key,則直接根據shard key計算出需要查詢的chunk,向對應的shard發送查詢請求
插入請求
寫操作必須包含shard key,mongos根據shard key算出文檔應該儲存到哪個chunk,然後將寫請求發送到chunk所在的shard。
更新/刪除請求
更新、刪除請求的查詢條件必須包含shard key或者_id,如果是包含shard key,則直接路由到指定的chunk,如果只包含_id,則需將請求發送至所有的shard。
其他命令請求
除增刪改查外的其他命令請求處理方式都不盡相同,有各自的處理邏輯,比如listDatabases命令,會向每個Shard及Config Server轉寄listDatabases請求,然後將結果進行合并。
如何串連
一個典型的ConnectURI 結構如下:
mongodb://[username:[email protected]]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]//說明- mongodb:// 首碼,代表這是一個Connection String;- username:[email protected] 如果啟用了鑒權,需要指定使用者密碼;- hostX:portX多個 mongos 的地址清單;- /database鑒權時,使用者帳號所屬的資料庫;- ?options 指定額外的串連選項,比如指定readPreference=secondaryPreferred實現讀寫分離
分區叢集可以提供多個 mongos 實現現負載平衡;而當某個 mongos 故障時,用戶端也能自動進行 failover,將請求都分散到狀態正常的 mongos 上。
當 mongos 數量很多時,還可以按應用來將 mongos 進行分組,比如有2個應用 A、B、有4個 mongos,可以讓應用 A 訪問 mongos 1-2(URI 裡只指定 mongos 1-2 的地址),
應用 B 來訪問 mongos 3-4(URI 裡只指定 mongos 3-4 的地址),根據這種方法來實現應用間的訪問隔離(應用訪問的 mongos 彼此隔離,但後端 Shard 仍然是共用的),如
五、Config中繼資料
Config server儲存Sharded cluster的所有中繼資料,所有的中繼資料都儲存在config資料庫,
3.2版本後,Config Server可部署為一個獨立的複製集,極大的方便了Sharded cluster的營運管理。
config資料集合如下表所示:
集合名稱 |
說明 |
config.shards |
儲存各個Shard的資訊,可通過addShard、removeShard命令來動態從Sharded cluster裡增加或移除shard |
config.databases |
儲存所有資料庫的資訊,包括DB是否開啟分區,primary shard資訊,對於資料庫內沒有開啟分區的集合,所有的資料都會儲存在資料庫的primary shard上 |
config.colletions |
資料分區是針對集合維度,某個資料庫開啟分區功能後,如果需要讓其中的集合分區儲存,則需調用shardCollection命令來針對集合開啟分區。 |
config.chunks |
集合分區開啟後,預設會建立一個新的chunk,shard key取值[minKey, maxKey]內的文檔(即所有的文檔)都會儲存到這個chunk。當使用Hash分區策略時,可以預先建立多個chunk,以減少chunk的遷移 |
config.settings |
儲存sharded cluster的配置資訊,比如chunk size,是否開啟balancer等 |
config.tags |
主要儲存sharding cluster標籤(tag)相關的你洗,以實現根據tag來分布chunk的功能 |
config.changelog |
主要儲存sharding cluster裡的所有變更操作,比如balancer遷移chunk的動作就會記錄到changelog裡。 |
config.mongos |
儲存當前叢集所有mongos的資訊 |
config.locks |
儲存鎖相關的資訊,對某個集合進行操作時,比如moveChunk,需要先擷取鎖,避免多個mongos同時遷移同一個集合的chunk。 |
六、分區均衡
Mongodb 實現了自動分區均衡,均衡器是一個在後台對分區chunk進行監控的進程,當某個shard的chunks差異數量到達閾值時,將自動開始在shard中間遷移chunk資料庫以達到均衡目的。整個遷移過程對應用程式層是透明的,從3.4版本開始,均衡器不再由Mongos執行,而是由Config複本集的主節點來處理。
遷移過程中對叢集效能存在一定影響,因此一般可以通過設定均衡視窗對齊到業務閑時段。
閾值參考表
|Number of Chunks| Migration Threshold|
|-|-|
|Fewer than 20| 2||
|20-79| 4|
|80 and greater| 8|
遷移過程
- 均衡器向源shard發送moveChunk命令;
- 源shard執行內部的moveChunk流程,過程中資料操作仍然指向當前shard
- 目標shard構建缺失的索引;
- 目標shard請求並接收chunk副本資料;
- 在chunk接收到後,目標shard向源shard確認是否存在累加式更新資料,若存在則繼續同步;
- 完全同步後,源shard通知config複本集更新中繼資料庫,將chunk的位置更新為目標shard
- 在更新完中繼資料庫後並確保沒有關聯cursor的情況下,源shard刪除被遷移的chunk副本。
參考文檔
mongodb shard cluster原理
http://www.mongoing.com/archives/2782
mongo中文社區-高可用mongodb叢集
https://yq.aliyun.com/articles/61516
官網-mongodb分區叢集
https://docs.mongodb.com/manual/core/sharding-balancer-administration/
mongodb分區擴充架構