走進MongoDB(五)---- 分片

 本文從如下幾個方面對MongoDB進行介紹mongodb

1、分片鍵組件shell

2、分片鍵數據庫

3、哈希分片數組

4、範圍分片緩存

5、區間安全

6、分片部署實例服務器

 

Sharding概述網絡

是分片、或者分區的意思。分片是一個數據庫架構,能夠經過key 範圍拆分數據而且把拆分後的數據分散的存儲到兩個或多個數據庫實例。分片提供了水平擴展的功能。架構

MongoDB使用分片來支持超大數據集和高操做性能的部署要求。咱們可使用兩種方法來支持數據量的大量增長和高性能操做要求:垂直擴展和水平擴展分佈式

一、垂直擴展:

一般是增長單機容量,例如、使用性能更高的CPU、增長內存、增長硬盤存儲空間。

二、水平擴展(mongodb使用sharding來支持水平擴展):

一般是將數據集進行分割,並將其分佈到過個服務器上。經過增長額外的服務器來增長性能、容量的需求。由於每一個機器只負責處理全部工做量的一個子集,其中的每一臺機器都不會要求特別高的容量和性能,這提供了比高配置的單機服務器更高的數據處理效率。面對部署集性能的擴展需求,只須要增長額外的服務器節點便可,這比使用高端硬件的單機服務器花費更低的成本。           

三、分片集羣

Mongodb分片集羣由如下組件構成:

Shard:每個分片都包含分片數據的一個子集。每個分片能夠被部署爲一個複本集。

Mongos:扮演一個查詢路由的角色,在客戶端程序和分片集羣之間提供了一個路由接口。

Config servers:存儲了集羣的元數據和配置設置。Mongodb3.4開始,config servers必需要部署爲一個複製集。

下圖描述了分片集羣中各組件之間的相互做用:

 

MongoDB把數據在表(collection)級別進行分區,將表數據分佈到集羣的各個分片上面。

四、分片鍵(shard key

爲了在collection中分佈documentsMongoDB使用shard key來分割collection。在目標collection中,分片鍵由每一個document中存在的不可變域(字段)組成。

當對一個collection進行分片的時候選擇使用分片鍵。在分片以後,分片鍵是不可更改的。一個分片的collection只能有一個分片鍵。

對一個非空collection作分片,collection必需要設置一個由分片鍵開始的索引。對一個空的collection作分片,若是collection沒有一個可用於分片鍵的合適的索引,mongodb會建立這個索引。

分片鍵的選擇會影響分片集羣的性能、效率和可擴展性。一個擁有高配置硬件環境和基礎設施的集羣可能會由於分片鍵的選擇而出現較大的瓶頸。

五、Chunks

Mongodb會把分片數據分割成塊。每個塊。。。。。。

Mongodb在分片集羣中使用分片集羣平衡器在多個分片之間進行chunks的遷移。平衡器會嘗試在集羣中全部分片之間保持chunks的對等與平衡。

注:平衡器是在後臺運行的程序,用於管理每個分片上chunks的數量。

六、分片的優點

/

MongoDB把讀寫工做量分佈到集羣中的多個分片上,容許每個分片處理一個集羣操做的子集。讀/寫工做量均可以經過在集羣中增長更多的分片來實現水平方向的擴展。

存儲容量

集羣中的每個分片包含集羣數據總量的一個子集。當數據量增加的時候,額外的分片能夠提高集羣的數據存儲容量。

高可用性

即便一個或者多個分片出現故障而不可用,分片集羣仍然能夠執行部分的讀寫操做。雖然,宕機期間故障分片上包含的數據子集是不可訪問的,可是指向其它可用分片上的讀寫操做仍然能夠成功執行。

Mongodb3.2開始,能夠把config servers(配置服務器,存儲分片集羣的相關元數據及配置信息)部署爲副本集。只要config servers的大部分副本可用,分片集羣就能夠繼續進行讀寫操做的處理。MongoDB3.4開始,再也不支持SCCCSync Config Connection Config,僅僅支持CSRSConfig Server Replication Set)。

在生產環境中,每個單獨的分片都應該被部署爲一個副本集,以保證數據的冗餘和可用性。

分片部署以前應該考慮的問題

分片集羣基礎設施須要和複雜性要求精心的計劃、執行和維護。

在選擇分片鍵的時候須要作一個仔細的考慮,由於這會直接影響集羣的性能和效率。在分片設置以後就不能再改變分片鍵,你也不能取消已經分片的collection

分片具備一個確切的操做要求和限制。

若是查詢不包含分片鍵或者複合分片鍵的前綴,mongos會執行一個廣播操做,將在集羣中的全部分片進行查詢。這種分散性的查詢操做會具備一個過長的運行時間。

七、分片collection和非分片collection

一個數據庫能夠同時擁有分片collection和非分片collection。分片集合被分割到集羣中的多個分片上,非分片集合只存儲在主分片節點。每個數據庫都有本身的主分片。

 

八、鏈接一個分片集羣

咱們必須先鏈接到mongos路由,在經過路由來和分片集羣中的collection進行數據交互。客戶端千萬不要直接鏈接到一個單獨的分片來執行讀寫操做。

 

咱們能夠像鏈接到mongod同樣鏈接到mongos。例如經過mongo shell或者mongodb driver

九、分片策略

MongoDB支持兩種將數據分佈到集羣各個分片上的分片策略。

Hashed sharding(哈希分片)

哈希分片會根據分片鍵的值計算出一個哈希值。以後每個chunk(數據塊)都被分配到基於分片鍵哈希值的一個範圍。

當使用哈希索引解析查詢時,mongodb會自動計算哈希值。

 

有一些分片鍵多是「靠近的」,他們的哈希值不太可能在同一個chunk。基於哈希的數據分配能夠幫助更加均勻的分配數據,特別是在那些分片鍵單調改變的數據集中。

可是,哈希分配意味着,分片鍵上基於範圍的查詢指向一個單獨分片的可能性會更小。致使集羣進行普遍的廣播操做()。

ranged sharding

範圍分片是將數據分割成基於分片鍵值的一個範圍。每個chunk被分配到基於分片鍵值的一個範圍。

 

一些值是相近的「分片鍵」更可能駐留在相同的chunk上。這容許targeted operations(定向操做)由於mongos只會把操做路由到包含所需數據的分片。

十、分片集羣中的區間(Zones in sharded clusters

在分片集羣中,基於分片鍵(shard key)你能夠爲分片數據建立區域(一組documents)。在集羣中,能夠將一個區域和一個或多個分片相互關聯。一個分片也能夠和多個不相互衝突的zones相關聯。在一個平衡的集羣中,MongoDB僅僅會在與zone相關聯的分片中,遷移被zone所包含的chunks

每個區域都會包含一個或多個分片鍵值區域。每個zone中所包含的範圍老是包括它的下界、不包括它的上界。就是[ 1 , 10 ) :  1<=range<10

  

若是在zone中定義一個新的範圍,必須使用包含在分片鍵裏的域。若是使用混合分片鍵,那麼這個範圍必需要包含分片鍵的前綴。

在選擇分片鍵的時候,要仔細考慮將來使用區域分片的可能性,由於在collection分片以後就不能夠再更改分片鍵了。

Collations in sharding(分片中的字符串比對規則)

使用帶有 collation:{locale:」simple」} 選項的shardCollection命令對一個具備默認比對規則的collection作分片。成功的分片又如下要求:

1.collection必須擁有一個前綴是分片鍵的索引。

2.索引必須具備{ locale : 「simple」 }比對規則。

若使用比對規則建立了collection,在分片collection以前要確保知足以前的條件。

 

1、分片集羣組件

生產環境部署

在一個生產部署環境下,要確保數據的冗餘和系統的高可用性。參考如下分片集羣生產部署方案:

1 把配置服務器部署爲3節點的複製集。

2 把每一個分片部署爲3節點的複製集

3 部署一個或多個mongos路由

在可能的狀況下,在一個適合做爲災難恢復的地點爲每個複製集中部署一個節點。

分片集羣要求至少要把數據分佈到兩個分片上。若是計劃在將來須要的時候啓動一個分片,可是在部署時並不須要此分片,這時候咱們能夠部署一個單分片的分片集羣。

能夠爲每個應用服務器部署一個mongos路由來確保每一個服務器均可以始終如一的訪問分片集羣。可選的,也能夠在應用程序和mongos組中間部署一組mongos路由,而且使用一個代理或者負載平衡器。

開發環境部署

若是隻是用於測試和開發,能夠部署一個具備最小數量組件的分片集羣。參考如下開發環境部署:

1 具備一個成員的配置服務器複製集

2 至少一個配置爲單節點複製集的分片

3 一個mongos實例

 

分片

全部的分片在一塊兒組成了集羣的整個數據集。

用戶、客戶端、應用程序都應該只鏈接到一個單獨的分片來執行本地管理和維護操做。

在單獨分片上的查詢只會返回數據的一個子集。要鏈接到mongos才能執行集羣級別的查詢(包括讀、寫操做)。

注:mongodb不能保證兩個連續的chunks會駐留在同一個分片上。

1 主分片

分片集羣上的每個數據庫都有一個主分片,主分片持有了全部沒有分片的collection。主分片和複製集中的主節點沒有任何關係。

在建立一個新的數據庫的時候,Mongos經過選擇集羣中具備最小數據量的那個分片做爲主分片。Mongos使用由listDatabase 命令返回的totalSize域做爲選擇標準的一部分。

    

使用movePrimary命令來改變數據庫的主分片。主分片的遷移過程可能會話費大量的時間才能完成,在處理完成以前都不該該訪問collection中的數據。

當使用以前部署爲複製集的服務器來做爲分片配置爲分片集羣的時候,全部以前存在的數據都繼續駐留在以前所在的位置。接下來建立的數據庫可能駐留在集羣上的任何一個分片上。

2 分片狀態

mongo shell中使用sh.status()方法查看集羣的信息報告。這個報告包含:哪一個分片是主分片、chunk(數據庫)在全部分片上的分佈。

分片集羣安全

可使用內部認證來阻止沒有經過認證的組件進入集羣。

分片的本地用戶

每一個分片都支持role-baseed access control,從而限制weigh未認證的用戶訪問分片數據(經過--auth選項來開啓)。另外,也可使用Internal authentication(內部認證)來進行訪問控制。

每一個分片都有其本身的本地分片用戶。這些用戶不能用於其它分片,也不能用於經過mongos來鏈接分片集羣。

 

配置服務器(metadata

存儲分片集羣的元數據。元數據包含全部集羣中數據和組件的狀態和阻止形式,包含了每個分片上的chunks列表和定義在chunk裏的範圍。

Mongos緩存這些數據,而且用它們把讀寫操做路由到正確的分片上。當集羣的元數據因爲chunk分裂、新增分片而發生改變時,mondos也會更新想這些緩存。

配置服務器也會存儲權限配置信息(如,基於角色的訪問控制、內部認證)。

MongoDB也會使用配置服務器來管理分佈式鎖。

配置服務器複製集

MongoDB3.2開始,使用配置服務器複製集來提升一致性,由於MongoDB能夠採起標準配置服務器複製集讀寫協議。另外,可使分片集羣能夠有3個以上的配置服務器,由於每個複製集均可以最多配置50個。要將配置服務器部署爲複製集,必須使用WireTiger存儲引擎。

限制:

1 不能有arbiters成員

2 不能有延時成員

3 必須構建索引

配置服務器上的讀寫操做

1

Admin數據庫包含了與認證、受權相關的colletion,另外還有一些用於內部使用的system.* colletion

Config數據庫中的collection包含了分片集羣的元數據。當metadata變化時,mongodbconfig數據庫寫入數據。

在正常數據庫操做和維護的過程當中,用戶不要直接向config數據庫直接寫入數據。

當對config進行寫入時,mongodb使用majority級別的寫入確認(write concern

2

MongoDBadmin數據庫讀認證、受權數據和其它內部使用的數據。

當啓動mongos或者metadata改變以後,MongoDB都會從config數據庫讀數據。分片也會從config服務器讀取數據庫元數據。

讀數據的時候,會使用majority級別的read concern

配置服務器可用性

若是配置服務器丟失了主節點,而且沒法成功選舉一個新的主節點,集羣元數據變成只讀模式。這時,仍然能夠對分片進行讀寫,可是不能夠進行chunk的遷移、分割。若是全部的配置服務器都不能夠,集羣也是不可操做的。

Mongos緩存了配置服務器的元數據。全部配置服務器不可用的時候,若是mongos實例沒有重啓,仍然可使用集羣,直到配置服務器回恢復使用。若是重啓了mongosmongos將不能再對讀寫進行路由操做。

沒有元數據,集羣就是不可操做的。保證配置服務器的完整、可用、備份是很是重要的。與存儲在集羣分片上的其它數據相比,配置服務器數據量很小,並且具備相對更低的活動負載。

分片集羣元數據

訪問config數據庫,須要鏈接mongos實例,而後使用:

Use config

一般狀況下,不該該對config服務器中的數據進行直接的更改。Config數據庫包含的collections:

changelog

chunks

collections

databases

lockpings

locks

mongos

settings

shards

Version

分片集羣的安全性

使用內部認證來設置集羣內的安全,防止未受權的集羣組件訪問集羣。爲了設置內部認證,必須啓動集羣中的每個mongod而且進行合適的安全設置。

路由(mongos

Mongos負責將查詢和寫操做路由到一個分片上。從應用程序看來mongos只提供了到分片集羣的接口。

Mongos經過使用緩存的metadata來追蹤哪些數據在哪個分片上。

最多見的作法是和應用程序服務器同一個系統上運行mongos實例,而在其它專用服務器或者分片上來維護mongos實例。

路由和結果處理

路由查詢步驟

1 肯定必須接收查詢的分片列表。

2 在全部目標分片上創建一個指針。

Mongos從每個目標分片中合併數據並返回document。像sorting等這樣的查詢修飾符,會在monogos實例檢索結果以前,在一個分片上先執行查詢過濾。

3.2版本開始,若是操做不要求在主分片上執行,在多個分片上運行聚合操做的時候,這些操做能夠將結果路由到任何分片以合併結果,並避免重載該數據的主分片。

當查詢包含分片鍵或者分片鍵的前綴,mongos會執行目標操做(將查詢路由到集羣的分片子集)。

對於不包含分片鍵的查詢,mongos執行一個廣播查詢(到全部的分片檢索數據)。可是,有些包含分片鍵的查詢仍然會進行廣播式查詢,這取決於數據在集羣中的分佈和查詢的選擇性。

Mongos如何處理查詢修飾符

1 sorting

若是使用sort()指針函數,則主分片會合並據結果並對其進行sort排序,最後經過mongos將數據返回給客戶端。

2 limits

Mongoslimit發送給全部分片,在將數據返回給客戶端以前,對結果集從新執行limit

3 skips

Mongos不會將skip參數發送給分片,而是從分片上檢索未經跳過的結果,在結果所有組合後再跳過指定數量的documents

可是,當skiplimit一塊兒使用的時候,mongos會將它們一塊兒發送給分片,用以提升操做的執行效率。

 

確認鏈接到mongos實例

使用isMaster命令來肯定是否鏈接到mongoss。例如:

{

   "ismaster" : true,

   "msg" : "isdbgrid",

   "maxBsonObjectSize" : 16777216,

   "ok" : 1

}

若是鏈接到mongodd,返回結果裏不會有isdbgrid這個字符串。

查詢隔離

一般,分片環境中最快速的查詢是:使用分片鍵和來自config server的元數據,將操做路由到一個單獨的分片上。這些目標操做使用分片鍵來定位知足查詢要求的documents所在的分片或者分片子集。

不包含分片鍵的查詢必須查詢全部分片,這是一種比較耗時的操做。

1 廣播操做

Mongos對全部分片上的collection進行廣播查詢。除非其能夠肯定哪個或幾個分片儲存了要查詢的數據。

    

一旦mongos收到全部分片的相應,它會合並數據並返回結果documents。 廣播操做的性能取決於集羣的整體負載,以及網絡延遲、單個分片負載和每一個分片返回的文檔數量等變量。 只要有可能,都有利於有針對性地進行廣播操做的操做。

多更新操做(updateMany() deleteMany())老是執行廣播操做

儘量的使用能夠出發目標操做的操做,而不是致使廣播操做的操做。

2 目標操做

Mongos使用分片鍵值來定位chunk(它的範圍包括分片鍵值)並把查詢指向抱哈chunk的分片。

    

例如,分片鍵以下:

{ a: 1, b: 1, c: 1 }

Mongos會把包含完整分片鍵或者以下所示的分片鍵前綴的查詢路由到一個指定的分片或者分片子集:

{ a: 1 }

{ a: 1, b: 1 }

全部的insertOne()會指向一個分片。insertMany()的每個document數組會指向一個單獨的分片,可是不能保證數組中的全部documents都插入到一個分片中。

全部updateOne()replaceOne()deleteOne()操做必須包含分片鍵或者_id。不然MongoDB會返回錯誤。

Depending on the distribution of data in the cluster and the selectivity of the query, mongosmay still perform a broadcast operation to fulfill these queries.

3 索引使用

若是查詢不包含分片鍵,mongos會將查詢發送到全部分片。相應的,每個分片會使用分片鍵索引或者其它更有效的索引來完成查詢。

若是查詢包含由分片鍵和輔助索引索引的字段的多個子表達式,則能夠將查詢路由到特定的分片,而且分片將使用可以最有效地執行的索引。

分片集羣安全性(RBAC和內部認證機制)

 

2、分片鍵

分片鍵肯定集合中documents的分佈。分片鍵是存在於集合中每一個文檔的索引字段或者索引的複合字段。

MongDB鍵值的範圍對集合中的數據進行分區。 每一個範圍定義了不重疊的分片鍵值範圍,並與一個塊相關聯。

MongoDB嘗試在羣集中的碎片之間均勻分配塊。 分片鍵與塊分佈的有效性有直接的關係。

 

一旦分割了一個集合,分片鍵和分片鍵值是不可變的;

您不能爲該集合選擇不一樣的分片鍵。

您不能更新分片鍵字段的值。

分片鍵規格

要分割一個集合,必須爲sh.shardCollection()方法指定目標集合和分片鍵:

Sh.shardCollection(namespance,key)

Namespace參數有字符串<database>.<collection>來指定。

Key參數由一個包含該字段的文檔和該字段的索引遍歷方向組成。

分片鍵索引

全部分片的集合必須具備一個支持分片鍵的索引;即索引能夠是分片鍵上的索引或分片鍵是索引的前綴的複合索引。

若是集合爲空,則sh.shardCollection()在分片鍵上建立索引,由於此索引尚不存在。

若是集合不爲空,則必須先使用sh.shardCollection()建立索引。

若是刪除分片鍵的最後一個有效索引,則經過在分片鍵上從新建立索引進行恢復。

1、惟一索引

對於分片集合,只有_id字段索引和分片鍵上的索引或分片鍵是前綴的複合索引能夠是惟一的:

1 您不能在其餘字段上分割具備惟一索引的集合。

2 您沒法在分片集合的其餘字段上建立惟一索引。

經過使用分片鍵上的惟一索引,MongoDB能夠在分片鍵值上強制執行惟一性。 MongoDB在整個組合鍵上強制執行惟一性,而不是分片鍵的單個組件。 要在分片鍵值上強制執行惟一性,請將惟一參數做爲true傳遞給sh.shardCollection()方法:

1 若是集合爲空,這樣的索引頁不存在,sh.shardCollection()則在分片鍵上建立惟一的索引。

2 若是集合不爲空,則必須先使用sh.shardCollection()建立索引。

雖然您可使用分片鍵是前綴的惟一組合索引,若是使用惟一參數,則該集合必須在分片鍵上具備惟一的索引。

您不能在哈希索引上指定惟一約束。

分片鍵的選擇(影響chunk在集羣上的分佈)

理想的分片鍵容許MongoDB在整個集羣中均勻分佈文檔。

 

1、集合大小

當分割不爲空的集合時,分片鍵只能限制初始分片操做支持集合的最大值。

2、分片鍵基數

分片鍵的基數決定了平衡器產生chunks的最大值。這會下降或者消除集羣的水平擴展效用。

一個惟一分片鍵值只能存在任意給定的一個chunk裏。若是分片鍵基數爲4,那麼分片集羣中不會超過4chunks,而且每個chunk存儲了一個惟一分片鍵的值。這會把有效分片的數量限制爲4個,而且擴展額外的分片是沒有意義的。

下圖,描述了將字段X設置爲分片鍵。若是X基數很小,新數據的插入將以下方式分佈到各個分片:

 

上例中的集羣不可以水平擴展,由於全部寫入操做都會被路由到當前分片的子集。

設置有很高基數的分片鍵也不能保證數據在分片集羣中的均勻分佈,可是能夠更好的支持水平擴展。分片鍵的變化頻率和比率也會有助於數據的分佈。選擇分片鍵的時候要把每一個因素都考慮進去。

若是數據模型要求分片鍵使用一個較小基數,那麼考慮使用組合索引,使用一個具備相對較高基數的字段。

分片鍵頻率

考慮一個表示分片鍵值範圍的集合-分片鍵頻率表明給定值在數據中出現的頻率。若是大多數documents只包含這些值的一部分,那麼存儲這些document的塊(chunks)將成爲集羣中的瓶頸。此外,隨着這些塊 的增加,它們會變得不可分割,由於它們不能再被進一步的分裂。這會下降或者消除集羣的水平擴展效用。

下圖,描述了將字段X設置爲分片鍵。若是X值的子集以高頻的方式發生,則插入數據的分佈以下全部:

 

分片鍵的基數和變化率都有助於數據的分佈。

若是必須使用分片鍵的高頻值,考慮使用組合索引,並使用惟一索引或者低頻值。

單調變化的分片鍵

單調遞增或遞減的分片鍵值更可能致使大部分數據都進入同一個分片。

這是由於,每一集羣中都有一個上限爲maxKey的塊,maxkey比任何值都高。Minkey也相似。

若是,分片鍵值一直增長,全部新插入的數據都將路由到上限爲maxkey的塊。同理,一直遞減的也是同樣。

單調遞增分片鍵值的數據插入,以下圖:

 

若是必須使用單調變化的分片鍵值,考慮使用哈希分片。

 

3、哈希分片

介紹見概述

 

4、範圍分片

介紹見概述 

 

5、區域/區間

區間概念見shard概述。

使用三個分片、兩個區間的分片集羣以下:

 

Behavior and Operations

一、Ranges

每一個區間包含一個或多個分片鍵值範圍。區間形式:[ )

二、Balancer

在全部分片上均勻的分佈數據。

對於每一個標記爲遷移的chunk,平衡器會檢查每一個可能目標分片的配置區間。若是chunk的範圍落在某個區間內,平衡器會把chunk遷移到這個區間所在的分片。不包含在任何區間內的chunk可能被融合到集羣中的任意一個分片。

在爲分片集羣配置區間,並分配到各個分片以後,集羣會花費一些時間來融合受配置影響的數據。這依賴於集羣中區塊的分割和當前的數據分佈。當平衡調整結束以後,全部包含在區間內的讀寫操做都會被路由到相應的分片上。

三、Shard key

當定義zone的新範圍時,必須使用分片鍵中包含的字段。若是使用複合分片鍵,則範圍必須包含分片鍵的前綴。

例如,給定一個分片鍵{a1b2c3},建立或更新一個區域來覆蓋b的值須要包括a,將a做爲前綴。建立或更新區域以覆蓋c的值須要包括ab,將ab做爲前綴。

您不能使用分片鍵中不存在的字段建立zone。例如,若是要根據地理位置對數據進行分區,則分片鍵至少須要一個包含地理數據的字段。

爲集合選擇分片鍵時,請考慮可能要用於配置區域的字段。分片後,將不能再更改分片鍵。

四、Hashed shard keys and zones

若使用哈希分片鍵,zone區間爲a :  [ 1 , 5 ) 範圍中1表明的是a的哈希值,而不是a的實際值。所以mongodb不能保證將a值在15之間的documents查詢都路由到分片上的同一個區間。

5Shard Zone Boundaries

分片區域的範圍始終包含下界、不包含上界。

 

6、分片部署實例

待完善 。。。。

相關文章
相關標籤/搜索