分片(sharding)是MongoDB用來將大型集合分割到不一樣服務器(或者說一個集羣)上所採用的方法。儘管分片起源於關係型數據庫分區,但MongoDB分片徹底又是另外一回事。html
和MySQL分區方案相比,MongoDB的最大區別在於它幾乎能自動完成全部事情,只要告訴MongoDB要分配數據,它就能自動維護數據在不一樣服務器之間的均衡。算法
高數據量和吞吐量的數據庫應用會對單機的性能形成較大壓力,大的查詢量會將單機的CPU耗盡,大的數據量對單機的存儲壓力較大,最終會耗盡系統的內存而將壓力轉移到磁盤IO上。數據庫
爲了解決這些問題,有兩個基本的方法: 垂直擴展和水平擴展。後端
垂直擴展:增長更多的CPU和存儲資源來擴展容量。服務器
水平擴展:將數據集分佈在多個服務器上。水平擴展即分片。架構
分片爲應對高吞吐量與大數據量提供了方法。使用分片減小了每一個分片須要處理的請求數,所以,經過水平擴展,集羣能夠提升本身的存儲容量和吞吐量。舉例來講,當插入一條數據時,應用只須要訪問存儲這條數據的分片.性能
使用分片減小了每一個分片存儲的數據。大數據
例如,若是數據庫1tb的數據集,並有4個分片,而後每一個分片可能僅持有256 GB的數據。若是有40個分片,那麼每一個切分可能只有25GB的數據。spa
1.對集羣進行抽象,讓集羣「不可見」設計
MongoDB自帶了一個叫作mongos的專有路由進程。mongos就是掌握統一路口的路由器,其會將客戶端發來的請求準確無誤的路由到集羣中的一個或者一組服務器上,同時會把接收到的響應拼裝起來發回到客戶端。
2.保證集羣老是可讀寫
MongoDB經過多種途徑來確保集羣的可用性和可靠性。將MongoDB的分片和複製功能結合使用,在確保數據分片到多臺服務器的同時,也確保了每分數據都有相應的備份,這樣就能夠確保有服務器換掉時,其餘的從庫能夠當即接替壞掉的部分繼續工做。
3.使集羣易於擴展
當系統須要更多的空間和資源的時候,MongoDB使咱們能夠按需方便的擴充系統容量。
組件 |
說明 |
Config Server |
存儲集羣全部節點、分片數據路由信息。默認須要配置3個Config Server節點。 |
Mongos |
提供對外應用訪問,全部操做均經過mongos執行。通常有多個mongos節點。數據遷移和數據自動平衡。 |
Mongod |
存儲應用數據記錄。通常有多個Mongod節點,達到數據分片目的。 |
分片集羣的構造
(1)mongos :數據路由,和客戶端打交道的模塊。mongos自己沒有任何數據,他也不知道該怎麼處理這數據,去找config server
(2)config server:全部存、取數據的方式,全部shard節點的信息,分片功能的一些配置信息。能夠理解爲真實數據的元數據。
(3)shard:真正的數據存儲位置,以chunk爲單位存數據。
Mongos自己並不持久化數據,Sharded cluster全部的元數據都會存儲到Config Server,而用戶的數據會分散存儲到各個shard。Mongos啓動後,會從配置服務器加載元數據,開始提供服務,將用戶的請求正確路由到對應的碎片。
Mongos的路由功能
當數據寫入時,MongoDB Cluster根據分片鍵設計寫入數據。
當外部語句發起數據查詢時,MongoDB根據數據分佈自動路由至指定節點返回數據。
在一個shard server內部,MongoDB仍是會把數據分爲chunks,每一個chunk表明這個shard server內部一部分數據。chunk的產生,會有如下兩個用途:
Splitting:當一個chunk的大小超過配置中的chunk size時,MongoDB的後臺進程會把這個chunk切分紅更小的chunk,從而避免chunk過大的狀況
Balancing:在MongoDB中,balancer是一個後臺進程,負責chunk的遷移,從而均衡各個shard server的負載,系統初始1個chunk,chunk size默認值64M,生產庫上選擇適合業務的chunk size是最好的。MongoDB會自動拆分和遷移chunks。
分片集羣的數據分佈(shard節點)
(1)使用chunk來存儲數據
(2)進羣搭建完成以後,默認開啓一個chunk,大小是64M,
(3)存儲需求超過64M,chunk會進行分裂,若是單位時間存儲需求很大,設置更大的chunk
(4)chunk會被自動均衡遷移。
適合業務的chunksize是最好的。
chunk的分裂和遷移很是消耗IO資源;chunk分裂的時機:在插入和更新,讀數據不會分裂。
chunksize的選擇:
小的chunksize:數據均衡是遷移速度快,數據分佈更均勻。數據分裂頻繁,路由節點消耗更多資源。大的chunksize:數據分裂少。數據塊移動集中消耗IO資源。一般100-200M
隨着數據的增加,其中的數據大小超過了配置的chunk size,默認是64M,則這個chunk就會分裂成兩個。數據的增加會讓chunk分裂得愈來愈多。
這時候,各個shard 上的chunk數量就會不平衡。這時候,mongos中的一個組件balancer 就會執行自動平衡。把chunk從chunk數量最多的shard節點挪動到數量最少的節點。
chunkSize 對分裂及遷移的影響
MongoDB 默認的 chunkSize 爲64MB,如無特殊需求,建議保持默認值;chunkSize 會直接影響到 chunk 分裂、遷移的行爲。
chunkSize 越小,chunk 分裂及遷移越多,數據分佈越均衡;反之,chunkSize 越大,chunk 分裂及遷移會更少,但可能致使數據分佈不均。可能形成熱點數據問題
chunkSize 過小,容易出現 jumbo chunk(即shardKey 的某個取值出現頻率很高,這些文檔只能放到一個 chunk 裏,沒法再分裂)而沒法遷移;chunkSize 越大,則可能出現 chunk 內文檔數太多(chunk 內文檔數不能超過 250000 )而沒法遷移。
chunk 自動分裂只會在數據寫入時觸發,因此若是將 chunkSize 改小,系統須要必定的時間來將 chunk 分裂到指定的大小。
chunk 只會分裂,不會合並,因此即便將 chunkSize 改大,現有的 chunk 數量不會減小,但 chunk 大小會隨着寫入不斷增加,直到達到目標大小。
MongoDB中數據的分片是以集合爲基本單位的,集合中的數據經過片鍵(Shard key)被分紅多部分。其實片鍵就是在集合中選一個鍵,用該鍵的值做爲數據拆分的依據。
因此一個好的片鍵對分片相當重要。片鍵必須是一個索引,經過sh.shardCollection加會自動建立索引(前提是此集合不存在的狀況下)。一個自增的片鍵對寫入和數據均勻分佈就不是很好,由於自增的片鍵總會在一個分片上寫入,後續達到某個閥值可能會寫到別的分片。可是按照片鍵查詢會很是高效。
隨機片鍵對數據的均勻分佈效果很好。注意儘可能避免在多個分片上進行查詢。在全部分片上查詢,mongos會對結果進行歸併排序。
對集合進行分片時,你須要選擇一個片鍵,片鍵是每條記錄都必須包含的,且創建了索引的單個字段或複合字段,MongoDB按照片鍵將數據劃分到不一樣的數據塊中,並將數據塊均衡地分佈到全部分片中。
爲了按照片鍵劃分數據塊,MongoDB使用基於範圍的分片方式或者 基於哈希的分片方式。
注意:
分片鍵是不可變。
分片鍵必須有索引。
分片鍵大小限制512bytes。
分片鍵用於路由查詢。
MongoDB不接受已進行collection級分片的collection上插入無分片
鍵的文檔(也不支持空值插入)
Sharded Cluster支持將單個集合的數據分散存儲在多shard上,用戶能夠指定根據集合內文檔的某個字段即shard key來進行範圍分片(range sharding)。
對於基於範圍的分片,MongoDB按照片鍵的範圍把數據分紅不一樣部分。
假設有一個數字的片鍵:想象一個從負無窮到正無窮的直線,每個片鍵的值都在直線上畫了一個點。MongoDB把這條直線劃分爲更短的不重疊的片斷,並稱之爲數據塊,每一個數據塊包含了片鍵在必定範圍內的數據。在使用片鍵作範圍劃分的系統中,擁有」相近」片鍵的文檔極可能存儲在同一個數據塊中,所以也會存儲在同一個分片中。
分片過程當中利用哈希索引做爲分片的單個鍵,且哈希分片的片鍵只能使用一個字段,而基於哈希片鍵最大的好處就是保證數據在各個節點分佈基本均勻。
對於基於哈希的分片,MongoDB計算一個字段的哈希值,並用這個哈希值來建立數據塊。在使用基於哈希分片的系統中,擁有」相近」片鍵的文檔極可能不會存儲在同一個數據塊中,所以數據的分離性更好一些。
Hash分片與範圍分片互補,能將文檔隨機的分散到各個chunk,充分的擴展寫能力,彌補了範圍分片的不足,但不能高效的服務範圍查詢,全部的範圍查詢要分發到後端全部的Shard才能找出知足條件的文檔。
1、遞增的sharding key
數據文件挪動小。(優點)
由於數據文件遞增,因此會把insert的寫IO永久放在最後一片上,形成最後一片的寫熱點。同時,隨着最後一片的數據量增大,將不斷的發生遷移至以前的片上。
2、隨機的sharding key
數據分佈均勻,insert的寫IO均勻分佈在多個片上。(優點)
大量的隨機IO,磁盤不堪重荷。
3、混合型key
大方向隨機遞增,小範圍隨機分佈。
爲了防止出現大量的chunk均衡遷移,可能形成的IO壓力。咱們須要設置合理分片使用策略(片鍵的選擇、分片算法(range、hash))
分片注意:
分片鍵是不可變、分片鍵必須有索引、分片鍵大小限制512bytes、分片鍵用於路由查詢。
MongoDB不接受已進行collection級分片的collection上插入無分片鍵的文檔(也不支持空值插入)
轉自:https://www.cnblogs.com/clsn/p/8214345.html#auto_id_0