MongoDB分片(Sharding)技術


分片(sharding)是MongoDB用來將大型集合分割到不同服務器(或者說一個集群)上所采用的方法。盡管分片起源於關系型數據庫分區,但MongoDB分片完全又是另一回事。

和MySQL分區方案相比,MongoDB的最大區別在於它幾乎能自動完成所有事情,只要告訴MongoDB要分配數據,它就能自動維護數據在不同服務器之間的均衡。

2.1 MongoDB分片介紹

2.1.1 分片的目的

  高數據量和吞吐量的數據庫應用會對單機的性能造成較大壓力,大的查詢量會將單機的CPU耗盡,大的數據量對單機的存儲壓力較大,最終會耗盡系統的內存而將壓力轉移到磁盤IO上。

  為了解決這些問題,有兩個基本的方法: 垂直擴展和水平擴展。

    垂直擴展:增加更多的CPU和存儲資源來擴展容量。

    水平擴展:將數據集分布在多個服務器上。水平擴展即分片。

2.1.2 分片設計思想

  分片為應對高吞吐量與大數據量提供了方法。使用分片減少了每個分片需要處理的請求數,因此,通過水平擴展,集群可以提高自己的存儲容量和吞吐量。舉例來說,當插入一條數據時,應用只需要訪問存儲這條數據的分片.

  使用分片減少了每個分片存儲的數據。

  例如,如果數據庫1tb的數據集,並有4個分片,然后每個分片可能僅持有256 GB的數據。如果有40個分片,那么每個切分可能只有25GB的數據。

 

2.1.3 分片機制提供了如下三種優勢

1.mongos 對集群進行抽象,讓集群“不可見”

  mongodb中沒有failover機制,官方建議是將mongos和應用服務器部署在一起,多個應用服務器就要部署多個mongos實例。mongos作為統一路口的路由器,其會將客戶端發來的請求准確無誤的路由到集群中的一個或者一組服務器上,同時會把接收到的響應拼裝起來發回到客戶端。

mongos的高可用可以用有幾種方法可以使這三個mongos接口都利用起來,減少單個接口的壓力。常用的有LVS和HAProxy。於是嘗試用HAProxy做負載均衡。

-------------------------------------------------------------------------------------------------------

mongodb 可以以單復制集的方式運行,client 直連 mongod 讀取數據。

單復制集的方式下,數據的水平擴展的責任推給了業務層解決(分實例,分庫分表),mongodb 原生提供集群方案,該方案的簡要架構如下:

mongodb集群是一個典型的去中心化分布式集群。mongodb集群主要為用戶解決了如下問題:

  • 元數據的一致性與高可用(Consistency + Partition Torrence)
  • 業務數據的多備份容災(由復制集技術保證)
  • 動態自動分片
  • 動態自動數據均衡

下文通過介紹 mongodb 集群中各個組成部分,逐步深入剖析 mongodb 集群原理。

ConfigServer

mongodb 元數據全部存放在configServer中,configServer 是由一組(至少三個)MongoDb實例組成的集群。

ConfigServer 的唯一功能是提供元數據的增刪改查。和大多數元數據管理系統(etcd,zookeeper)類似,也是保證一致性與分區容錯性。本身不具備中心化的調度功能。

ConfigServer與復制集

ConfigServer 的分區容錯性(P)和數據一致性(C)是復制集本身的性質。

mongodb 的讀寫一致性由 WriteConcern 和 ReadConcern 兩個參數保證。

writeConcern

readConcern

兩者組合可以得到不同的一致性等級。

指定 writeConcern:majority 可以保證寫入數據不丟失,不會因選舉新主節點而被回滾掉。

readConcern:majority + writeConcern:majority 可以保證強一致性的讀

readConcern:local + writeConcern:majority 可以保證最終一致性的讀

mongodb 對configServer全部指定writeConcern:majority 的寫入方式,因此元數據可以保證不丟失。

對 configServer 的讀指定了 ReadPreference:PrimaryOnly 的方式,在 CAP 中舍棄了A與P得到了元數據的強一致性讀。

Mongos

數據自動分片

對於一個讀寫操作,mongos 需要知道應該將其路由到哪個復制集上,mongos通過將片鍵空間划分為若干個區間,計算出一個操作的片鍵的所屬區間對應的復制集來實現路由。

Collection1 被划分為4個chunk,其中

chunk1 包含(-INF,1) , chunk3 包含[20, 99) 的數據,放在shard1上。

chunk2 包含 [1,20), chunk4 包含[99, INF) 的數據,放在shard2上。

chunk 的信息存放在configServer 的mongod實例的 config.chunks 表中,格式如下:

{   
    "_id" : "mydb.foo-a_\"cat\"", "lastmod" : Timestamp(1000, 3), "lastmodEpoch" : ObjectId("5078407bd58b175c5c225fdc"), "ns" : "mydb.foo", "min" : { "animal" : "cat" }, "max" : { "animal" : "dog" }, "shard" : "shard0004" } 

值得注意的是:chunk是一個邏輯上的組織結構,並不涉及到底層的文件組織方式。

-------------------------------------------------------------------------------------------------------

 

2.保證集群總是可讀寫

  MongoDB通過多種途徑來確保集群的可用性和可靠性。將MongoDB的分片和復制功能結合使用,在確保數據分片到多台服務器的同時,也確保了每分數據都有相應的備份,這樣就可以確保有服務器換掉時,其他的從庫可以立即接替壞掉的部分繼續工作。

3.使集群易於擴展

  當系統需要更多的空間和資源的時候,MongoDB使我們可以按需方便的擴充系統容量。

2.1.4 分片集群架構

組件

說明

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根據數據分布自動路由至指定節點返回數據。

2.2 集群中數據分布

2.2.1 Chunk是什么

  在一個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會被自動均衡遷移。

2.2.2 chunksize的選擇

  適合業務的chunksize是最好的。

  chunk的分裂和遷移非常消耗IO資源;chunk分裂的時機:在插入和更新,讀數據不會分裂。

  chunksize的選擇:

  小的chunksize:數據均衡是遷移速度快,數據分布更均勻。數據分裂頻繁,路由節點消耗更多資源。大的chunksize:數據分裂少。數據塊移動集中消耗IO資源。通常100-200M

2.2.3 chunk分裂及遷移

  隨着數據的增長,其中的數據大小超過了配置的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 大小會隨着寫入不斷增長,直到達到目標大小

2.3 數據區分

2.3.1 分片鍵shard key

  MongoDB中數據的分片是以集合為基本單位的,集合中的數據通過片鍵(Shard key)被分成多部分。其實片鍵就是在集合中選一個鍵,用該鍵的值作為數據拆分的依據。

  所以一個好的片鍵對分片至關重要。片鍵必須是一個索引,通過sh.shardCollection加會自動創建索引(前提是此集合不存在的情況下)。一個自增的片鍵對寫入和數據均勻分布就不是很好,因為自增的片鍵總會在一個分片上寫入,后續達到某個閥值可能會寫到別的分片。但是按照片鍵查詢會非常高效

  隨機片鍵對數據的均勻分布效果很好。注意盡量避免在多個分片上進行查詢。在所有分片上查詢,mongos會對結果進行歸並排序。

  對集合進行分片時,你需要選擇一個片鍵,片鍵是每條記錄都必須包含的,且建立了索引的單個字段或復合字段,MongoDB按照片鍵將數據划分到不同的數據塊中,並將數據塊均衡地分布到所有分片中

  為了按照片鍵划分數據塊,MongoDB使用基於范圍的分片方式或者 基於哈希的分片方式。

注意:

分片鍵是不可變。

分片鍵必須有索引。

分片鍵大小限制512bytes。

分片鍵用於路由查詢。

MongoDB不接受已進行collection級分片的collection上插入無分片

鍵的文檔(也不支持空值插入)

2.3.2 以范圍為基礎的分片Sharded Cluster

  Sharded Cluster支持將單個集合的數據分散存儲在多shard上,用戶可以指定根據集合內文檔的某個字段即shard key來進行范圍分片(range sharding)。

 

 

  對於基於范圍的分片,MongoDB按照片鍵的范圍把數據分成不同部分。

  假設有一個數字的片鍵:想象一個從負無窮到正無窮的直線,每一個片鍵的值都在直線上畫了一個點。MongoDB把這條直線划分為更短的不重疊的片段,並稱之為數據塊,每個數據塊包含了片鍵在一定范圍內的數據。在使用片鍵做范圍划分的系統中,擁有”相近”片鍵的文檔很可能存儲在同一個數據塊中,因此也會存儲在同一個分片中。

2.3.3 基於哈希的分片

  分片過程中利用哈希索引作為分片的單個鍵,且哈希分片的片鍵只能使用一個字段,而基於哈希片鍵最大的好處就是保證數據在各個節點分布基本均勻。

 

 

  對於基於哈希的分片,MongoDB計算一個字段的哈希值,並用這個哈希值來創建數據塊。在使用基於哈希分片的系統中,擁有”相近”片鍵的文檔很可能不會存儲在同一個數據塊中,因此數據的分離性更好一些。

  Hash分片與范圍分片互補,能將文檔隨機的分散到各個chunk,充分的擴展寫能力,彌補了范圍分片的不足,但不能高效的服務范圍查詢,所有的范圍查詢要分發到后端所有的Shard才能找出滿足條件的文檔。

2.3.4 分片鍵選擇建議

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM