當mongodb複制集遇到下面的業務場景時,你就需要考慮使用sharded cluster
存儲容量需求超出單機磁盤容量
活躍的資料集超出單機記憶體容量,導緻很多請求都要從磁盤讀取資料,影響性能
寫iops超出單個mongodb節點的寫服務能力

如上圖所示,sharding cluster使得集合的資料可以分散到多個shard(複制集或者單個mongod節點)存儲,使得mongodb具備了橫向擴充(scale out)的能力,豐富了mongodb的應用場景。
sharded cluster由shard、mongos和config server 3個元件構成。
mongos是sharded cluster的通路入口,強烈建議所有的管理操作、讀寫操作都通過mongos來完成,以保證cluster多個元件處于一緻的狀态。
mongos本身并不持久化資料,sharded cluster所有的中繼資料都會存儲到config server(下一節詳細介紹),而使用者的資料則會分散存儲到各個shard。mongos啟動後,會從config server加載中繼資料,開始提供服務,将使用者的請求正确路由到對應的shard。
sharded cluster支援将單個集合的資料分散存儲在多個shard上,使用者可以指定根據集合内文檔的某個字段即shard key來分布資料,目前主要支援2種資料分布的政策,範圍分片(range based sharding)或hash分片(hash based sharding)。
如上圖所示,集合根據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分片是根據使用者的shard key計算hash值(64bit整型),根據hash值按照『範圍分片』的政策将文檔分布到不同的chunk。
hash分片與範圍分片互補,能将文檔随機的分散到各個chunk,充分的擴充寫能力,彌補了範圍分片的不足,但不能高效的服務範圍查詢,所有的範圍查詢要分發到後端所有的shard才能找出滿足條件的文檔。
選擇shard key時,要根據業務的需求及『範圍分片』和『hash分片』2種方式的優缺點合理選擇,同時還要注意shard key的取值一定要足夠多,否則會出現單個jumbo chunk,即單個chunk非常大并且無法分裂(split);比如某集合存儲使用者的資訊,按照age字段分片,而age的取值非常有限,必定會導緻單個chunk非常大。
mongos作為sharded cluster的通路入口,所有的請求都由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請求,然後将結果進行合并。
config server存儲sharded cluster的所有中繼資料,所有的中繼資料都存儲在config資料庫,3.2版本後,config server可部署為一個獨立的複制集,極大的友善了sharded cluster的運維管理。
config.shards集合存儲各個shard的資訊,可通過addshard、removeshard指令來動态的從sharded cluster裡增加或移除shard。如下所示,cluster目前擁有2個shard,均為複制集。
如下指令,針對shtest資料裡的hello集合開啟分片,使用x字段作為shard key來進行範圍分片。
集合分片開啟後,預設會建立一個新的chunk,shard key取值[minkey, maxkey]内的文檔(即所有的文檔)都會存儲到這個chunk。當使用hash分片政策時,可以預先建立多個chunk,以減少chunk的遷移。
當chunk裡寫入的資料量增加到一定門檻值時,會觸發chunk分裂,将一個chunk的範圍分裂為多個chunk,當各個shard上chunk數量不均衡時,會觸發chunk在shard間的遷移。如下所示,shtest.coll的一個chunk,在寫入資料後分裂成3個chunk。
config.settings集合裡主要存儲sharded cluster的配置資訊,比如chunk size,是否開啟balancer等
config.changelog主要存儲sharding cluster裡的所有變更操作,比如balancer遷移chunk的動作就會記錄到changelog裡;
config.mongos存儲目前叢集所有mongos的資訊;
config.locks存儲鎖相關的資訊,對某個集合進行操作時,比如movechunk,需要先擷取鎖,避免多個mongos同時遷移同一個集合的chunk。
<a href="https://yq.aliyun.com/articles/64?spm=0.0.0.0.9jrpm8" target="_blank">mongodb複制集架構原理</a>
<a href="https://docs.mongodb.org/manual/core/sharding-introduction/" target="_blank">mongodb sharding簡介</a>
<a href="https://docs.mongodb.org/manual/core/sharded-cluster-shards/" target="_blank">primary shard</a>
<a href="https://docs.mongodb.org/manual/reference/method/sh.enablesharding/" target="_blank">enablesharding指令</a>
<a href="https://docs.mongodb.org/manual/reference/command/moveprimary/" target="_blank">moveprimary指令</a>
<a href="https://docs.mongodb.org/manual/reference/command/shardcollection/" target="_blank">shardcollection</a>
<a href="https://docs.mongodb.org/manual/reference/command/nav-sharding/" target="_blank">sharding的管理操作</a>
<a href="https://docs.mongodb.org/manual/tutorial/deploy-shard-cluster/" target="_blank">部署sharded cluster</a>