分片機制
1. 數據切分
首先(xian),基于(yu)分(fen)(fen)片切(qie)分(fen)(fen)后的(de)(de)(de)數據塊稱為 chunk,一個(ge)(ge)分(fen)(fen)片后的(de)(de)(de)集(ji)(ji)合會(hui)包含多(duo)個(ge)(ge) chunk,每個(ge)(ge) chunk 位于(yu)哪個(ge)(ge)分(fen)(fen)片(Shard) 則記錄在 Config Server(配(pei)置服務(wu)器)上(shang)。Mongos 在操作分(fen)(fen)片集(ji)(ji)合時,會(hui)自動根據分(fen)(fen)片鍵找到對應(ying)的(de)(de)(de) chunk,并(bing)向該 chunk 所在的(de)(de)(de)分(fen)(fen)片發起操作請求。
數據是根據分片策略來進行切分的,而分片策略則由 分片鍵(ShardKey)+分片算法(ShardStrategy)組成。MongoDB 支持兩種(zhong)分(fen)片算(suan)法:
- 范圍分片:將整個取值范圍劃分為多個chunk,每個chunk(默認配置為64MB)包含其中一小段的數據,范圍分片能很好的滿足范圍查詢的需求,比如想查詢x的值在[-30, 10]之間的所有文檔,這時 Mongos 直接能將請求路由到具體的Chunk,就能查詢出所有符合條件的文檔。 但范圍分片的缺點在于,如果 ShardKey 有明顯遞增(或者遞減)趨勢,則新插入的文檔多會分布到同一個chunk,無法擴展寫的能力,比如使用_id作為 ShardKey,而MongoDB自動生成的id高位是時間戳,是持續遞增的。
- 哈希分片:Hash分片是根據用戶的 ShardKey 先計算出hash值(64bit整型),再根據hash值按照范圍分片的策略將文檔分布到不同的 chunk。由于 hash值的計算是隨機的,因此 Hash 分片具有很好的離散性,可以將數據隨機分發到不同的 chunk 上。 Hash 分片可以充分的擴展寫能力,彌補了范圍分片的不足,但不能高效的服務范圍查詢,所有的范圍查詢要查詢多個 chunk 才能找出滿足條件的文檔。
2. 保證均衡
數據是分布在不同的 chunk上的,而 chunk 則會分配到不同的分片上,那么如何保證分片上的數據(chunk) 是均衡的呢?
在(zai)真實的場景(jing)中,會存在(zai)下面兩種情況:
-
A. 全預分配,chunk 的數量和 shard 都是預先定義好的,比如 10個shard,存儲1000個chunk,那么每個shard 分別擁有100個chunk。
此時集群已經是均衡的狀態(tai) -
B. 非預分配,這(zhe)(zhe)種情況則比較復(fu)雜(za),一般當一個 chunk 太大(da)時(shi)(shi)會產生分裂(split),不(bu)(bu)斷分裂的(de)結(jie)果會導致(zhi)不(bu)(bu)均(jun)(jun)衡(heng);或者(zhe)動態擴(kuo)容增加分片時(shi)(shi),也會出現(xian)不(bu)(bu)均(jun)(jun)衡(heng)的(de)狀(zhuang)態。 這(zhe)(zhe)種不(bu)(bu)均(jun)(jun)衡(heng)的(de)狀(zhuang)態由集群均(jun)(jun)衡(heng)器(qi)進(jin)行檢測,一旦(dan)發現(xian)了不(bu)(bu)均(jun)(jun)衡(heng)則執行 chunk數(shu)據的(de)搬遷(qian)達(da)到均(jun)(jun)衡(heng)。
MongoDB 的(de)(de)數據均衡器(qi)運(yun)行(xing)于 Primary Config Server(配置服務器(qi)的(de)(de)主節(jie)點)上,而該節(jie)點也(ye)同時會控制 Chunk 數據的(de)(de)搬遷流程(cheng)。對于數據的(de)(de)不均衡是(shi)根據兩個(ge)分(fen)片(pian)上的(de)(de) Chunk 個(ge)數差異來判定的(de)(de),閾值對應表如(ru)下:
| Chunk的數量 | 遷移閾值 |
| <20 | 2 |
| 20~79 | 4 |
| >80 | 8 |
MongoDB 的數(shu)據遷(qian)移(yi)對集群性(xing)能存(cun)在一定(ding)影響,這點無法避(bi)免,目前的規避(bi)手段(duan)只能是(shi)將均衡窗(chuang)口對齊(qi)到(dao)業務閑時段(duan)。