亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

MongoDB 分片原理

2023-08-18 03:57:24
57
0

近年來,互聯網數據出現了爆炸式增長,單機數據庫在容量和性能上往往難以滿足各個互聯網服務的需求。在此背景下,很多數據庫通過支持橫向擴展能力來滿足業務需求,通過分片的方式將數據打散到多臺服務器上,使得整體性能和容量得到成倍提升。
MongoDB 從(cong)最(zui)初設計(ji)上考慮到了海(hai)量(liang)數據的需求(qiu),因此原(yuan)生就支持分片(pian)(pian)集群。本文(wen)將(jiang)對 MongoDB 的分片(pian)(pian)原(yuan)理進行分析,闡述分片(pian)(pian)架構和實(shi)現(xian)原(yuan)理,并(bing)說明使(shi)用分片(pian)(pian)的注意事項。

MongoDB 分片(pian)架構

MongoDB 的分(fen)片架構如下,包含(han) 3 ;種角色:

  • mongos: 作為分片集群(qun)的(de)接(jie)入(ru)層,接(jie)受用(yong)戶的(de)讀寫請(qing)求,并根據路由轉發到底層 shard.  1 個分片集群(qun)可(ke)以有 1 個或者(zhe)多(duo)個  mongos 節(jie)點。
  • shard:1 個 shard 存儲了一部分分片表的(de)數據,1 個分片集(ji)群(qun)可以有 1 個或者多(duo)個 shard. 每(mei)個 shard 有多(duo)個 mongod 節(jie)點組成的(de)副本集(ji)構(gou)成。
  • config servers: 存儲(chu)配置元(yuan)數(shu)據以(yi)及分片(pian)表的(de)(de)路由(you)等(deng)信(xin)息(xi)。 1 個(ge)分片(pian)集(ji)群有(you) 1 個(ge) config servers, config servers 是由(you)多個(ge) mongod 節點組(zu)成的(de)(de)副本集(ji)。

從 0 開(kai)始探究分(fen)片原(yuan)理

分(fen)片無非是(shi)選(xuan)好 shardKey 之后(hou),按照(zhao)某種(zhong)規則將數據均(jun)(jun)勻分(fen)布到多個(ge)shard 中,保(bao)證每個(ge) shard 的數據量(liang)和請求量(liang)基本(ben)均(jun)(jun)衡。因此,本(ben)質上來說要解決 2 個(ge)核心問題:

  1. 如(ru)何(he)選擇 shardKey?
  2. 如(ru)何(he)選取(qu)合適(shi)的分片算法(fa)?

ShardKey 選取

分片鍵(jian)的(de)選取需要(yao)保障數(shu)據分布足夠離散,每個(ge)分片的(de)存儲(chu)容量(liang)均衡(heng),并(bing)能夠將(jiang)數(shu)據操作均勻分發到集(ji)群中的(de)所有分片中。

如果(guo)分片(pian)鍵選取不佳(jia),可能會導(dao)致(zhi)各個分片(pian)負(fu)載(zai)不均,出現 jumbo chunk 導(dao)致(zhi)無法分裂等問題。而且分片(pian)鍵一旦(dan)確定之后(hou),不能在(zai)運行過程中進(jin)行變(bian)更,需要按(an)新分片(pian)鍵創(chuang)建(jian)新表后(hou)重新導(dao)入數據(4.4及(ji)以上版本支(zhi)持 shardKey 變(bian)更,但(dan)是并不建(jian)議做這(zhe)種在(zai)線操作)。

一般選取分片(pian)鍵時,會考慮以(yi)下因素:

1. 分片鍵的區分度

分(fen)片鍵的取(qu)值(zhi)基數(shu)決定(ding)了最(zui)多能(neng)包(bao)含多少個 chunk,如果取(qu)值(zhi)基數(shu)太(tai)小(xiao),則會導致 chunk 數(shu)量很(hen)低,可能(neng)會有負載不均的問題。

比如按照“性別”來設置(zhi)分片鍵就不是合理的選擇,因為(wei) “性別” 只有 “男”、“女” 2 種取(qu)值,這樣最(zui)多(duo) 2 個 chunk.

2. 分片鍵(jian)的(de)取值分布是否均勻(yun)

如果分(fen)片(pian)鍵的(de)取(qu)值存(cun)在熱點,也可能導致分(fen)片(pian)負載(zai)不均(jun)。比(bi)如以 “國家” 作為片(pian)建,會由(you)于(yu)各個(ge)國家之間人(ren)(ren)口(kou)的(de)差異(yi)出現負載(zai)不均(jun),人(ren)(ren)口(kou)多(duo)的(de)國家存(cun)儲(chu)量大請(qing)求多(duo),而(er)人(ren)(ren)口(kou)少的(de)國家存(cun)儲(chu)量小請(qing)求少。

對于這種場景,可以考慮使用復合鍵(jian)來作為分片鍵(jian),降低(di)出現熱點的概率。

3. 是否會(hui)按照分片鍵單調寫(xie)入

如果(guo)業務按照分片(pian)鍵遞(di)增或者遞(di)減(jian)的趨勢進行讀(du)寫,則可能在(zai)某(mou)(mou)一(yi)時(shi)刻請求集中在(zai)某(mou)(mou)個(ge) chunk 上,無法發揮(hui)集群多(duo)個(ge)分片(pian)的優勢。

比如對于存儲(chu)日志的場(chang)景,如果按照(zhao)日志創建時間進行范圍分(fen)(fen)片(pian),則在某(mou)一時間內一直對同(tong)一個(ge) chunk 進行寫入。對于這(zhe)種場(chang)景,可以考慮復合分(fen)(fen)片(pian)鍵或(huo)者哈(ha)希(xi)分(fen)(fen)片(pian)來(lai)避(bi)免這(zhe)種情況(kuang)。

4. 查詢模型是否(fou)包含分片鍵(jian)

在確定分片(pian)(pian)鍵(jian)后,需要考慮業(ye)務的(de)查(cha)詢(xun)請(qing)(qing)求(qiu)中是否包含有(you)分片(pian)(pian)鍵(jian)。mongos 節點會根據查(cha)詢(xun)請(qing)(qing)求(qiu)中的(de)分片(pian)(pian)鍵(jian)將(jiang)請(qing)(qing)求(qiu)轉發到(dao)對應的(de) shard server 中。如果(guo)查(cha)詢(xun)請(qing)(qing)求(qiu)中不包含分片(pian)(pian)鍵(jian),則(ze) mongos 節點會將(jiang)請(qing)(qing)求(qiu)廣播到(dao)后端的(de)所有(you)  shard server,進行(xing) scatter/gather 模式的(de)查(cha)詢(xun),此時查(cha)詢(xun)性能(neng)會有(you)所下(xia)降。

分片算法

傳統的(de) Hash

提到將數據(ju)打散,往(wang)往(wang)第(di)一個想到的(de)就是(shi) hash. 比如有 N 個 shard,可以通過 Hash(shardKey) mod N 的(de)方式(shi),將每(mei)條數據(ju)按照 shardKey 映射到 編(bian)號(hao)為 [0, N-1] 的(de) shard 中(zhong)。

這種簡單 hash 方式雖然(ran)將(jiang)數據打散的(de)非常均勻,但是無(wu)法處理增加和刪除 shard 的(de)問題,一旦(dan)出現 shard 變(bian)更(geng),所有(you)數據都要重新分布。

在實(shi)際的業務場景中,增加和(he)刪除 shard 是非常常見的操作(zuo)。因此,一般很(hen)少(shao)直(zhi)接使用(yong)簡單(dan) hash 的方式(shi)。

傳統(tong)的一致(zhi)性 Hash

一致性 hash 算法能夠解決簡單 hash 在 shard 數(shu)量變動時,所有數(shu)據需要重新分布(bu)的問題。

其基本思路(lu)時(shi)將hash 后(hou)的(de)線性空間(jian)當作一個環,然后(hou)根據 shard 個數在環上分(fen)配相(xiang)應的(de) node,每條數據根據 shardKey 計算(suan)出的(de) hash 值找到距離(li)最近的(de)弄得,而且 node 值不(bu)大于 hash 值。

如果新增(zeng)或者刪除 shard,會(hui)導致(zhi) node 發(fa)生變化,但是(shi)只有部(bu)分(fen)涉及到的數據需要重新分(fen)布。相比簡單 hash 方式,對(dui)系統的影響相對(dui)較小。

另外,通過(guo)引入虛擬 node,可以將重新分(fen)(fen)布時的數據(ju)遷移操(cao)作分(fen)(fen)散到多個節點,并且盡量保證均勻。

不過盡管如此,在增(zeng)加和刪除 node 時,仍然會出(chu)現數據不均衡的情況。

MongoDB 的 Range 分片

MongoDB 引入了(le) chunk 的(de)概念,作(zuo)(zuo)為分片、路(lu)由以及(ji)數(shu)(shu)據(ju)遷移的(de)單元。 1 個(ge)(ge)(ge) chunk 可以看(kan)作(zuo)(zuo)是(shi)(shi)分片表中(zhong) shardKey 連續排列的(de)數(shu)(shu)據(ju)集合(he),是(shi)(shi)一個(ge)(ge)(ge)邏輯概念,各個(ge)(ge)(ge) chunk 在底層存儲引擎(qing)中(zhong)并不(bu)是(shi)(shi)分開存儲。 1 個(ge)(ge)(ge) chunk 默認是(shi)(shi) 64MB,用(yong)戶也可以根據(ju)實際需要自(zi)(zi)行調整。1個(ge)(ge)(ge) chunk 中(zhong)的(de)數(shu)(shu)據(ju)數(shu)(shu)據(ju)總大小超過 64MB 會(hui)自(zi)(zi)動進行分裂,如果各個(ge)(ge)(ge) shard 之間 chunk 的(de)個(ge)(ge)(ge)數(shu)(shu)不(bu)均勻(yun),會(hui)自(zi)(zi)動觸發負載(zai)均衡(heng)操(cao)作(zuo)(zuo)。

以 shardKey 是 “x” 為例(li),其取值(zhi)空間由 1 個或(huo)者多個 chunk 組成(cheng):

需(xu)要注意(yi)的(de)是,1個(ge)(ge) chunk 只能分(fen)布(bu)在某(mou)1個(ge)(ge) shard中。如(ru)果讀請求是一個(ge)(ge)小范圍的(de)查詢,則 mongos 只需(xu)要將請求轉(zhuan)發(fa)到對(dui)應的(de) shard 上,這樣能充分(fen)利用 range 分(fen)片的(de)優勢(shi)。如(ru)果涉及(ji)多個(ge)(ge) shard, 則 mongos 需(xu)要使用 scatter/gather 方式(shi)和多個(ge)(ge) shard 交互。

MongoDB 的(de) Hash 分片

如果用戶的(de)(de)寫入(ru)(ru)操(cao)作(zuo)存在(zai)按 shardKey  的(de)(de)單調(diao)性,比如以時(shi)間(jian)戳(chuo)為 shardKey并按照時(shi)間(jian)順序寫入(ru)(ru)。此時(shi)會導致寫入(ru)(ru)操(cao)作(zuo)始終集中在(zai) shardKey 最大的(de)(de) chunk 上,壓力始終在(zai)某一個(ge) shard 中,而且會觸發大量的(de)(de)分裂和遷移操(cao)作(zuo)。對于 range 分片來說簡直就是災(zai)難。

MongoDB 的(de)(de) hash 分(fen)片方式能夠(gou)很好的(de)(de)解決這(zhe)個(ge)問題。和(he) range 分(fen)片不同,shardKey 首先會經過 hash函(han)數(md5)計算出一(yi)個(ge)整數類型的(de)(de) hash 值,然(ran)后根據這(zhe)個(ge) hash 值分(fen)散到(dao)對應的(de)(de) chunk 和(he) shard 上(shang)。如下圖所示。

Hash 函數(shu)對用戶(hu)來說是不感知的,而(er)且代碼中(zhong)固定為 md5 算法。

MongoDB 的 hash 分片算(suan)法和一致(zhi)性 hash 算(suan)法有點類(lei)似,但是不(bu)同(tong)之處在(zai)于(yu) chunk 分裂(lie)機制(zhi)和自動(dong)負載均衡(heng)機制(zhi)使(shi)得(de)數據(ju)分布理(li)論上(shang)更(geng)加均勻(yun)。

MongoDB 的 Zone 分區

MongoDB 可(ke)以(yi)根據 shardKey 對 shard 設(she)置(zhi) zone 屬(shu)性(xing),比如對于(yu)多地域部署場景,可(ke)以(yi)將(jiang)(jiang)華南機(ji)房的(de) shard 設(she)置(zhi)為 “South” zone,將(jiang)(jiang)華北機(ji)房的(de) shard 設(she)置(zhi)為 “North” zone,通過(guo)這(zhe)種(zhong)方式可(ke)以(yi)將(jiang)(jiang)對應的(de)數(shu)據限定在特定的(de) shard 中存儲。

Zone 必須按照 shardKey 或者 shardKey 的(de)前綴進行(xing)設置。屬于(yu)某個(ge)(ge) zone 的(de)數據,在數據遷移時(shi)只(zhi)會在同一個(ge)(ge) zone 的(de)多個(ge)(ge)shard 之間移動(dong)。

路由管理(li)

無論是 range 分(fen)片還是 hash 分(fen)片,都至少(shao)需(xu)要維護以下 2 種信(xin)息:

  • 表(biao)屬性元(yuan)數據。包括 shardKey、分片(pian)算法、創(chuang)建時間以及是(shi)否刪(shan)除等。
  • 路由信息。描述(shu)了每(mei)個 chunk 的取值范(fan)圍、存儲在哪個 shard、版本(ben)號(hao)信息等。

MongoDB 分片集群(qun)在 config ;server 節(jie)點上使用 config 庫存(cun)(cun)儲(chu)這(zhe)些信(xin)息(xi),其中 config.collections 表(biao)存(cun)(cun)儲(chu)了各個分片表(biao)的屬性(xing)元數據,config.chunks 表(biao)存(cun)(cun)儲(chu)了各個分片表(biao)的路由信(xin)息(xi)。

比(bi)如在一個 4.0 版本分(fen)片集群(qun)中(zhong),采用(yong) hash分(fen)片方式創建了一個分(fen)片表 db2.shardcoll1, 則 config.collections 存儲(chu)的屬性元數(shu)據(ju)為:

mongos> use config
switched to db config
mongos> db.collections.find({ "_id" : "db2.shardcoll1"}).pretty()
{
	"_id" : "db2.shardcoll1",  // 表名
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),  // 創建時間
	"lastmod" : ISODate("1970-02-19T17:02:47.297Z"),
	"dropped" : false,   // 是否被刪除
	"key" : {   // shardKey 和分片算法
		"a" : "hashed"
	},
	"unique" : false,   // shardKey是否具有唯一屬性
	"uuid" : UUID("0eafa40d-2b84-4326-9033-2cf8923a8c18")   // 唯一 ID
}

采用 hash 方式創建(jian)分片表(biao)后(hou),默認(ren)會生成 2 個 chunk,路由表(biao)為(wei):

mongos> use config
switched to db config
mongos> db.chunks.find({"ns" : "db2.shardcoll1"}).pretty()
{  // 第 1 個 chunk
	"_id" : "db2.shardcoll1-a_MinKey",  // 以表名和 chunk 的最小值作為 id
	"ns" : "db2.shardcoll1",   // 表名
	"min" : {  // 本 chunk 的最小值為 $minKey (包含)
		"a" : { "$minKey" : 1 }
	},
	"max" : {  // 本 chunk 的最大值為 0 (不包含)
		"a" : NumberLong(0)
	},
	"shard" : "sharding_shard1",  // 本 chunk 存儲在 sharding_shard1 上
	"lastmod" : Timestamp(1, 0),  // 版本號
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),  // 最近修改時間
	"history" : [  // 歷史記錄
		{
			"validAfter" : Timestamp(1690772924, 6),
			"shard" : "sharding_shard1"
		}
	]
}
{
	"_id" : "db2.shardcoll1-a_0",  // 以表名和 chunk 的最小值作為 id
	"ns" : "db2.shardcoll1",  // 表名
	"min" : {  // 本 chunk 的最小值為 0 (包含)
		"a" : NumberLong(0)
	},
	"max" : {  // 本 chunk 的最大值為 $maxKey (不包含)
		"a" : { "$maxKey" : 1 }
	},
	"shard" : "sharding_shard1",  // 本 chunk 存儲在 sharding_shard1 上
	"lastmod" : Timestamp(1, 1),   // 版本號
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),   // epoch 信息,最近修改時間
	"history" : [  // 歷史記錄
		{
			"validAfter" : Timestamp(1690772924, 6),
			"shard" : "sharding_shard1"
		}
	]
}

對于數據量很大的分片表(biao)(biao)來(lai)說,其(qi)路由表(biao)(biao)也是非常大的。按照 1 個(ge)(ge) chunk 默認 64 MB 來(lai)計算(suan),1個(ge)(ge) 6TB 的分片表(biao)(biao)對應(ying)的路由表(biao)(biao)會有 10 萬多(duo)條記錄。而且隨著(zhu)數據不斷(duan)寫入,chunk 不斷(duan)分(fen)裂使得(de)路由(you)表不斷(duan)更新,如何感知路由(you)變化以及快(kuai)速進行路由(you)同(tong)步就成了(le)非常關鍵的問題。

路由表(biao)版本(ben)

MongoDB 采(cai)用版本控(kong)制方式來追蹤路由變(bian)化,每個 chunk 的路由版本信息由 3 部分組(zu)成:

  • Major Version, 主(zhu)版(ban)本號,如果(guo)出現了遷移(yi)則 version 增加。
  • Minor Version, 小(xiao)版(ban)本,如(ru)果出現了 split 分裂則(ze) version 增加。
  • Epoch,ObjectId 類(lei)型的唯(wei)一 ID

根據上(shang)述 chunk version 派生(sheng)出 2 個概念:

  • Shard Version, 某個 shard 上維護的最高的 chunk version.
  • Collection Version, 分(fen)片表全局最高的 chunk version.

路由信息同(tong)步

Config server 上存儲的一定是最(zui)新(xin)而且(qie)最(zui)權威的路由(you)信息,mongos 和 mongod 的路由(you)信息都從 config server 增量獲取。

對于 mongos 節(jie)點會(hui)(hui)在(zai)內(nei)存(cun)中(zhong)維(wei)護路(lu)由(you)(you)信息(xi)(xi),啟動時沒有路(lu)由(you)(you)信息(xi)(xi),會(hui)(hui)從 config server 上做(zuo)一次全量拉取(qu)。對于 mongod 節(jie)點,會(hui)(hui)在(zai)內(nei)存(cun)中(zhong)維(wei)護路(lu)由(you)(you)信息(xi)(xi),而且會(hui)(hui)在(zai) config.cache.chunks.{ns} 表(biao)中(zhong)緩存(cun)路(lu)由(you)(you)信息(xi)(xi),而且這(zhe)個緩存(cun)路(lu)由(you)(you)信息(xi)(xi)的表(biao)會(hui)(hui)進行主(zhu)從同步。

路(lu)由(you)(you)信(xin)息的(de)更新整體(ti)上(shang)采用懶加載的(de)方式。具體(ti)來說,mongos 轉發給 mongod 的(de)請(qing)求會額外攜帶mongos 認為的(de)路(lu)由(you)(you)版本信(xin)息,mongod 在收到(dao)請(qing)求之后(hou)會先進行路(lu)由(you)(you)版本比較。如果發現有某一(yi)方的(de)版本比較舊,則先從(cong) config server 上(shang)拉(la)取到(dao)最新路(lu)由(you)(you)之后(hou)再(zai)進行請(qing)求重(zhong)試。如果 2 邊的(de)路(lu)由(you)(you)版本一(yi)樣,則正(zheng)常執(zhi)行請(qing)求。

Chunk 分裂

對于 4.0 及以下版本(ben),會在(zai) mongos 節點(dian)上記錄(lu)每個 chunk 的寫入(ru)情況(kuang)。對于 4.2 及以上版本(ben),會在(zai) mongod 節點(dian)上記錄(lu) chunk 的大小。

如果 ;chunk 的(de)大小(xiao)達到了設定的(de)閾值(默認 64MB),則會觸發 chunk 分裂。分為 2 個步驟:

  1. SplitVector,確定分裂點。大(da)致步驟為根(gen)據 shardKey 索(suo)引掃描(miao)出(chu) chunk 的文檔條(tiao)數以及平均文檔長度信息,然后(hou)將 chunk 劃(hua)分成(cheng)滿足(zu)閾值大(da)小的多個子 chunk。
  2. SplitChunk, 執行 chunk 分(fen)裂。由于(yu) chunk 只(zhi)是一個邏輯上(shang)的概念,因此不(bu)會涉(she)及(ji)存儲(chu)引(yin)擎(qing)側(ce)的表(biao)變(bian)更,只(zhi)會涉(she)及(ji)到路由信息變(bian)更。大致流程為(wei)將分(fen)裂出的chunk 信息提(ti)交到 config server 并(bing)刪除原先(xian)chunk 的路由信息,然后刷(shua)新 mongod 本地的路由表(biao)。

Balancer 數據均衡

Config server 主節點(dian)上會啟動一個后臺(tai)線程定期檢查(默認 2 次(ci)操作之間間隔 10 s)分片(pian)表(biao)的 chunks 數(shu)量在各個分片(pian)之間是(shi)否均衡。是(shi)否均衡的評判標準為chunk 數(shu)量最多的 shard 和 chunk 數(shu)量最少的 shard 之間的差值(zhi)是(shi)否超過了如下(xia)閾值(zhi):

如果滿足(zu)遷(qian)移條件,則(ze) config server 會(hui)通(tong)過(guo) moveChunk 命令,通(tong)知 shard 之間(jian)進行(xing) chunk 遷(qian)移。值得注意的是,chunk 數據移動不會(hui)經過(guo) config server,只(zhi)會(hui)在 shard 之間(jian)進行(xing),config server 只(zhi)會(hui)充(chong)當控制者(zhe)角色。

數據遷移(yi)是非常消耗資源的(de),從運營(ying)經驗來看,很多業(ye)務(wu)的(de)請(qing)求(qiu)毛刺(ci)都(dou)和(he)數據均衡操作有(you)關。因此,對于請(qing)求(qiu)延遲敏感或(huo)資源使用(yong)率(lv)較高的(de)用(yong)戶,盡量(liang)使用(yong) hash 分(fen)片保(bao)證(zheng)數據分(fen)布(bu)均勻,并將數據均衡窗口配(pei)置在業(ye)務(wu)低峰期。

使用 MongoDB 分片集群(qun)的注意(yi)事(shi)項

  1. 合理選(xuan)擇 shardKey,避免(mian)出現(xian)數據和請求傾斜(xie)的(de)情況,避免(mian)出現(xian) jumbo chunk 導致負載不均(jun)。
  2. 分片(pian)集(ji)群(qun)盡量(liang)(liang)創建(jian)分片(pian)表(biao)。如果確實需要創建(jian)非分片(pian)表(biao),也盡量(liang)(liang)不要放在(zai)(zai)同一個 db 中,避免出現該 db 所(suo)在(zai)(zai)的 primary shard 數據量(liang)(liang)過大或者負載過高。
  3. 使用(yong) hash 分(fen)(fen)片時(shi),盡量使用(yong)預分(fen)(fen)片時(shi)創建 initial chunks 的方式,這樣可以避(bi)免(mian)后續的 chunk 分(fen)(fen)裂和(he)遷移。
  4. 根據業(ye)務需(xu)求,配置合理的 balancer 運行窗口(kou),盡量避(bi)開業(ye)務高峰期。

總結(jie)

MongoDB 原生支持了非常(chang)完善的數(shu)據(ju)分(fen)片能(neng)力,通過(guo)數(shu)據(ju)分(fen)片也(ye)使(shi)得 MongoDB 在(zai)應對海(hai)量數(shu)據(ju)時游刃有余。MongoDB 支持 range 和 hash 分(fen)片方式,并通過(guo)配置 zone 分(fen)區來進(jin)行(xing)更(geng)加靈活(huo)的控(kong)制。

MongoDB 通過(guo)路由版本控制(zhi)來保(bao)證(zheng)路由信息(xi)在多個節點(dian)上的(de)一致(zhi)性,并(bing)通過(guo) chunk 自(zi)動分裂和遷(qian)移(yi)機制(zhi)保(bao)證(zheng)了數據均衡。

0條評論
0 / 1000
彭振翼
6文章數
1粉絲數
彭振翼
6 文章 | 1 粉(fen)絲
彭振翼
6文章數
1粉絲(si)數
彭振翼
6 文(wen)章 | 1 粉絲
原創

MongoDB 分片原理

2023-08-18 03:57:24
57
0

近年來,互聯網數據出現了爆炸式增長,單機數據庫在容量和性能上往往難以滿足各個互聯網服務的需求。在此背景下,很多數據庫通過支持橫向擴展能力來滿足業務需求,通過分片的方式將數據打散到多臺服務器上,使得整體性能和容量得到成倍提升。
MongoDB 從最初設計(ji)上考慮到了海(hai)量數(shu)據(ju)的需求,因此原(yuan)生(sheng)就支持分(fen)(fen)片(pian)(pian)集群。本文將對 MongoDB 的分(fen)(fen)片(pian)(pian)原(yuan)理進行分(fen)(fen)析(xi),闡(chan)述分(fen)(fen)片(pian)(pian)架構和(he)實現原(yuan)理,并說明使用分(fen)(fen)片(pian)(pian)的注(zhu)意(yi)事項(xiang)。

MongoDB 分片(pian)架構(gou)

MongoDB 的分片架構如下,包含 3 種角色:

  • mongos: 作為分(fen)片(pian)集群的接入層(ceng),接受用戶的讀寫(xie)請求,并根據路(lu)由轉發到(dao)底層(ceng) shard.  1 個(ge)(ge)分(fen)片(pian)集群可以有 1 個(ge)(ge)或者多個(ge)(ge)  mongos 節點。
  • shard:1 個(ge) shard 存儲了一部(bu)分分片表的(de)數據(ju),1 個(ge)分片集(ji)群(qun)可以有 1 個(ge)或者多個(ge) shard. 每個(ge) shard 有多個(ge) mongod 節點組成(cheng)的(de)副(fu)本集(ji)構成(cheng)。
  • config servers: 存儲(chu)配置元數據以(yi)及分片表的路由等信息。 1 個分片集(ji)群有 1 個 config servers, config servers 是由多(duo)個 mongod 節(jie)點(dian)組(zu)成的副本集(ji)。

從 0 開始探(tan)究分(fen)片原理

分(fen)(fen)片無非是選好 shardKey 之后(hou),按照某(mou)種規(gui)則將數據(ju)均勻分(fen)(fen)布到(dao)多個(ge)shard 中,保(bao)證每(mei)個(ge) shard 的數據(ju)量(liang)和請求量(liang)基本均衡。因此(ci),本質上來說要解決 2 個(ge)核心問題:

  1. 如何(he)選擇 shardKey?
  2. 如何選取合適的(de)分片算法(fa)?

ShardKey 選取

分(fen)片鍵的選(xuan)取需要保(bao)障數據(ju)分(fen)布足夠離(li)散,每(mei)個分(fen)片的存儲容量均(jun)衡,并(bing)能(neng)夠將數據(ju)操作均(jun)勻分(fen)發到集群中的所(suo)有分(fen)片中。

如果分(fen)片(pian)鍵選(xuan)取不佳,可(ke)能會導致各個(ge)分(fen)片(pian)負載(zai)不均,出(chu)現(xian) jumbo chunk 導致無法分(fen)裂(lie)等問題。而且分(fen)片(pian)鍵一旦確定之后(hou),不能在運行過(guo)程(cheng)中進行變更(geng),需(xu)要按新(xin)分(fen)片(pian)鍵創建(jian)新(xin)表后(hou)重新(xin)導入(ru)數(shu)據(ju)(4.4及以上版本(ben)支(zhi)持(chi) shardKey 變更(geng),但是并不建(jian)議做這種在線操作)。

一般選取分片鍵時,會考(kao)慮以(yi)下因素(su):

1. 分(fen)片鍵的(de)區分(fen)度

分片鍵的(de)取值基數決定了最多能(neng)包含(han)多少(shao)個 chunk,如果取值基數太(tai)小,則會(hui)導致 chunk 數量(liang)很低,可能(neng)會(hui)有(you)負(fu)載不均的(de)問題(ti)。

比如按(an)照“性別”來設置(zhi)分(fen)片鍵就不(bu)是合理的選(xuan)擇(ze),因為 “性別” 只有 “男”、“女” 2 種取值,這樣最多(duo) 2 個 chunk.

2. 分片(pian)鍵的取值(zhi)分布是(shi)否均(jun)勻(yun)

如果分片(pian)鍵的(de)取值存(cun)(cun)在熱點,也可能導致分片(pian)負載不均。比如以 “國(guo)(guo)家” 作(zuo)為(wei)片(pian)建,會由于各個國(guo)(guo)家之間人(ren)(ren)口的(de)差異出現負載不均,人(ren)(ren)口多(duo)的(de)國(guo)(guo)家存(cun)(cun)儲量大請(qing)求多(duo),而人(ren)(ren)口少的(de)國(guo)(guo)家存(cun)(cun)儲量小請(qing)求少。

對于(yu)這種場景,可(ke)以考慮使用復合鍵(jian)來作為分片鍵(jian),降低出現熱點的概率。

3. 是否(fou)會(hui)按照分(fen)片鍵單調寫入

如果業務按(an)照分(fen)片鍵遞(di)增或(huo)者遞(di)減的趨勢(shi)進行讀寫,則可能(neng)在(zai)(zai)某一(yi)時刻請求集(ji)中在(zai)(zai)某個 chunk 上,無法發揮集(ji)群(qun)多個分(fen)片的優勢(shi)。

比如對于(yu)存儲(chu)日(ri)(ri)志的場(chang)景,如果按照(zhao)日(ri)(ri)志創(chuang)建時(shi)間(jian)(jian)進(jin)行范圍分(fen)片,則在某一(yi)時(shi)間(jian)(jian)內一(yi)直對同(tong)一(yi)個(ge) chunk 進(jin)行寫入(ru)。對于(yu)這(zhe)種(zhong)場(chang)景,可以考(kao)慮復合分(fen)片鍵或者哈希(xi)分(fen)片來避免這(zhe)種(zhong)情況。

4. 查(cha)詢模型是(shi)否包含分片鍵

在確定分(fen)(fen)片(pian)(pian)鍵后(hou),需要考慮業(ye)務的(de)(de)查(cha)詢(xun)請(qing)求(qiu)(qiu)中是否(fou)包含有分(fen)(fen)片(pian)(pian)鍵。mongos 節點(dian)(dian)會(hui)(hui)根據查(cha)詢(xun)請(qing)求(qiu)(qiu)中的(de)(de)分(fen)(fen)片(pian)(pian)鍵將(jiang)(jiang)請(qing)求(qiu)(qiu)轉發到對應(ying)的(de)(de) shard server 中。如果查(cha)詢(xun)請(qing)求(qiu)(qiu)中不包含分(fen)(fen)片(pian)(pian)鍵,則(ze) mongos 節點(dian)(dian)會(hui)(hui)將(jiang)(jiang)請(qing)求(qiu)(qiu)廣播到后(hou)端的(de)(de)所有  shard server,進行 scatter/gather 模式的(de)(de)查(cha)詢(xun),此(ci)時查(cha)詢(xun)性能會(hui)(hui)有所下降。

分(fen)片算法

傳統的 Hash

提到(dao)(dao)將(jiang)數(shu)據打散(san),往(wang)往(wang)第一個(ge)想到(dao)(dao)的(de)就是 hash. 比如有 N 個(ge) shard,可(ke)以通過 Hash(shardKey) mod N 的(de)方(fang)式(shi),將(jiang)每條數(shu)據按照 shardKey 映射到(dao)(dao) 編號為 [0, N-1] 的(de) shard 中。

這種簡(jian)單(dan) hash 方式雖然將數(shu)據打散的非常均勻,但(dan)是(shi)無法處(chu)理增加和刪除 shard 的問(wen)題,一旦(dan)出(chu)現(xian) shard 變更,所(suo)有數(shu)據都要重新分布(bu)。

在實際的業務場(chang)景中(zhong),增加和刪(shan)除(chu) shard 是非常常見(jian)的操(cao)作。因此,一般很少直接(jie)使用簡單(dan) hash 的方式。

傳統的(de)一(yi)致(zhi)性 Hash

一致性 hash 算法能夠解決簡單 hash 在 shard 數(shu)量變動時,所有(you)數(shu)據需(xu)要重(zhong)新分(fen)布(bu)的(de)問(wen)題(ti)。

其基本思路時將hash 后的(de)(de)線性(xing)空間當作一個環,然后根(gen)據(ju) shard 個數(shu)在環上分配(pei)相(xiang)應(ying)的(de)(de) node,每條數(shu)據(ju)根(gen)據(ju) shardKey 計算出的(de)(de) hash 值(zhi)找到距離最近的(de)(de)弄得(de),而且 node 值(zhi)不(bu)大于(yu) hash 值(zhi)。

如果(guo)新(xin)增或者刪除 shard,會導致 node 發生(sheng)變化,但是只有部分涉(she)及(ji)到的(de)(de)數據需要重新(xin)分布。相比簡單 hash 方(fang)式,對系統的(de)(de)影(ying)響(xiang)相對較小。

另外,通(tong)過引入虛擬(ni) node,可(ke)以將重新分(fen)布時的數(shu)據遷移操作分(fen)散到多個(ge)節點,并且盡(jin)量(liang)保(bao)證(zheng)均勻。

不過盡(jin)管如此(ci),在增加和刪除 node 時,仍然(ran)會出現(xian)數據不均(jun)衡的情(qing)況(kuang)。

MongoDB 的 Range 分片(pian)

MongoDB 引入了 chunk 的(de)概念,作(zuo)為分(fen)片、路由以及數(shu)據(ju)遷移的(de)單元(yuan)。 1 個 chunk 可以看作(zuo)是(shi)分(fen)片表中(zhong) shardKey 連續排列的(de)數(shu)據(ju)集(ji)合,是(shi)一個邏輯(ji)概念,各(ge)(ge)個 chunk 在底層存(cun)儲(chu)引擎中(zhong)并不是(shi)分(fen)開(kai)存(cun)儲(chu)。 1 個 chunk 默認是(shi) 64MB,用戶也可以根據(ju)實際(ji)需要自行調整。1個 chunk 中(zhong)的(de)數(shu)據(ju)數(shu)據(ju)總大(da)小超過 64MB 會(hui)自動進(jin)行分(fen)裂,如果各(ge)(ge)個 shard 之間 chunk 的(de)個數(shu)不均(jun)(jun)勻,會(hui)自動觸發負載均(jun)(jun)衡操作(zuo)。

以 shardKey 是(shi) “x” 為例,其取值空間由(you) 1 個或者多個 chunk 組成:

需要注意(yi)的是,1個 chunk 只能分(fen)布在某1個 shard中。如(ru)果(guo)讀請(qing)求是一(yi)個小(xiao)范圍的查(cha)詢,則(ze) mongos 只需要將請(qing)求轉發到(dao)對應(ying)的 shard 上,這樣能充分(fen)利用(yong) range 分(fen)片的優(you)勢。如(ru)果(guo)涉及多(duo)個 shard, 則(ze) mongos 需要使用(yong) scatter/gather 方式(shi)和(he)多(duo)個 shard 交互(hu)。

MongoDB 的 Hash 分片(pian)

如(ru)果用(yong)戶的(de)寫(xie)入操作存在(zai)按 shardKey  的(de)單調性,比如(ru)以時(shi)(shi)間(jian)戳(chuo)為 shardKey并按照(zhao)時(shi)(shi)間(jian)順序(xu)寫(xie)入。此(ci)時(shi)(shi)會導致寫(xie)入操作始(shi)終集中在(zai) shardKey 最大(da)的(de) chunk 上,壓(ya)力始(shi)終在(zai)某一個(ge) shard 中,而(er)且會觸發大(da)量的(de)分(fen)裂和遷(qian)移操作。對(dui)于(yu) range 分(fen)片來說(shuo)簡直就是災難(nan)。

MongoDB 的(de) hash 分片方式能夠很好的(de)解決這個問題。和(he) range 分片不(bu)同,shardKey 首先會經過 hash函數(shu)(md5)計算出一個整(zheng)數(shu)類型的(de) hash 值,然后根據這個 hash 值分散到對應的(de) chunk 和(he) shard 上(shang)。如下圖所示。

Hash 函(han)數對用戶來說是不感(gan)知的,而且代碼中固(gu)定為 md5 算法。

MongoDB 的 hash 分(fen)片(pian)算法和(he)一致性 hash 算法有(you)點類(lei)似,但是不同之處(chu)在于 chunk 分(fen)裂機制(zhi)和(he)自動(dong)負載均(jun)衡機制(zhi)使(shi)得數據(ju)分(fen)布理論上更加均(jun)勻。

MongoDB 的 Zone 分(fen)區

MongoDB 可(ke)以(yi)根據 shardKey 對 shard 設(she)置 zone 屬性,比如對于多地域部(bu)署場景(jing),可(ke)以(yi)將(jiang)華(hua)(hua)南機(ji)房的(de) shard 設(she)置為(wei) “South” zone,將(jiang)華(hua)(hua)北(bei)機(ji)房的(de) shard 設(she)置為(wei) “North” zone,通過(guo)這種方式可(ke)以(yi)將(jiang)對應的(de)數據限定(ding)在特定(ding)的(de) shard 中(zhong)存儲。

Zone 必須按照 shardKey 或者 shardKey 的(de)前綴進行設置。屬于某個 ;zone 的(de)數據(ju),在數據(ju)遷移時(shi)只會(hui)在同一個 zone 的(de)多個shard 之間(jian)移動。

路由管理

無論是 range 分(fen)片還(huan)是 hash 分(fen)片,都至少需(xu)要(yao)維護以下 2 種信息:

  • 表屬性(xing)元數(shu)據(ju)。包括 shardKey、分片(pian)算法、創建時間以及(ji)是(shi)否刪除等。
  • 路(lu)由(you)信息(xi)。描述了每個(ge)(ge) chunk 的取值范圍、存(cun)儲在哪個(ge)(ge) shard、版(ban)本(ben)號信息(xi)等。

MongoDB 分(fen)(fen)片集群在 config server 節點上使用 config 庫存(cun)儲這些信(xin)(xin)息(xi),其中 config.collections 表存(cun)儲了各(ge)個分(fen)(fen)片表的屬性元數(shu)據,config.chunks 表存(cun)儲了各(ge)個分(fen)(fen)片表的路由信(xin)(xin)息(xi)。

比如在一(yi)個 4.0 版本分片集群中,采用(yong) hash分片方式創建了一(yi)個分片表(biao) db2.shardcoll1, 則 config.collections 存儲的屬性元數據為:

mongos> use config
switched to db config
mongos> db.collections.find({ "_id" : "db2.shardcoll1"}).pretty()
{
	"_id" : "db2.shardcoll1",  // 表名
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),  // 創建時間
	"lastmod" : ISODate("1970-02-19T17:02:47.297Z"),
	"dropped" : false,   // 是否被刪除
	"key" : {   // shardKey 和分片算法
		"a" : "hashed"
	},
	"unique" : false,   // shardKey是否具有唯一屬性
	"uuid" : UUID("0eafa40d-2b84-4326-9033-2cf8923a8c18")   // 唯一 ID
}

采(cai)用 hash 方式創建分片表后(hou),默認會(hui)生成 2 個 chunk,路由(you)表為:

mongos> use config
switched to db config
mongos> db.chunks.find({"ns" : "db2.shardcoll1"}).pretty()
{  // 第 1 個 chunk
	"_id" : "db2.shardcoll1-a_MinKey",  // 以表名和 chunk 的最小值作為 id
	"ns" : "db2.shardcoll1",   // 表名
	"min" : {  // 本 chunk 的最小值為 $minKey (包含)
		"a" : { "$minKey" : 1 }
	},
	"max" : {  // 本 chunk 的最大值為 0 (不包含)
		"a" : NumberLong(0)
	},
	"shard" : "sharding_shard1",  // 本 chunk 存儲在 sharding_shard1 上
	"lastmod" : Timestamp(1, 0),  // 版本號
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),  // 最近修改時間
	"history" : [  // 歷史記錄
		{
			"validAfter" : Timestamp(1690772924, 6),
			"shard" : "sharding_shard1"
		}
	]
}
{
	"_id" : "db2.shardcoll1-a_0",  // 以表名和 chunk 的最小值作為 id
	"ns" : "db2.shardcoll1",  // 表名
	"min" : {  // 本 chunk 的最小值為 0 (包含)
		"a" : NumberLong(0)
	},
	"max" : {  // 本 chunk 的最大值為 $maxKey (不包含)
		"a" : { "$maxKey" : 1 }
	},
	"shard" : "sharding_shard1",  // 本 chunk 存儲在 sharding_shard1 上
	"lastmod" : Timestamp(1, 1),   // 版本號
	"lastmodEpoch" : ObjectId("64c725bcdae50f066c478c7f"),   // epoch 信息,最近修改時間
	"history" : [  // 歷史記錄
		{
			"validAfter" : Timestamp(1690772924, 6),
			"shard" : "sharding_shard1"
		}
	]
}

對(dui)于數據量很大(da)的(de)(de)分片表(biao)來(lai)(lai)說,其路由表(biao)也是非(fei)常大(da)的(de)(de)。按(an)照 1 個(ge) chunk 默(mo)認 64 MB 來(lai)(lai)計算,1個(ge) 6TB 的(de)(de)分片表(biao)對(dui)應的(de)(de)路由表(biao)會有(you) 10 萬多條(tiao)記(ji)錄。而(er)且隨著數據不斷(duan)(duan)寫(xie)入,chunk 不斷(duan)(duan)分裂使得路(lu)(lu)由(you)(you)表不斷(duan)(duan)更新,如何(he)感知路(lu)(lu)由(you)(you)變化以(yi)及快(kuai)速進(jin)行(xing)路(lu)(lu)由(you)(you)同步就成了非常關鍵(jian)的問題(ti)。

路由表(biao)版(ban)本

MongoDB 采用(yong)版本控制方式(shi)來追蹤路由(you)變化,每個 chunk 的路由(you)版本信息由(you) 3 部分組(zu)成(cheng):

  • Major ;Version, 主版本號,如果(guo)出現了遷移則(ze) version 增加。
  • Minor Version, 小版本,如(ru)果出現了(le) split 分裂(lie)則 version 增加。
  • Epoch,ObjectId 類(lei)型的唯一 ID

根據(ju)上述 ;chunk version 派生出 2 個概念(nian):

  • Shard Version, 某個 shard 上(shang)維護的最高的 chunk version.
  • Collection Version, 分(fen)片(pian)表(biao)全局最高的(de) chunk version.

路由信息同步(bu)

Config server 上存儲的(de)一定是最(zui)新而(er)且(qie)最(zui)權(quan)威的(de)路(lu)由信息,mongos 和(he) mongod 的(de)路(lu)由信息都(dou)從 config server ;增量獲(huo)取(qu)。

對(dui)于 mongos 節(jie)點會(hui)在內存中(zhong)維護(hu)路(lu)由(you)信(xin)息,啟(qi)動時沒(mei)有(you)路(lu)由(you)信(xin)息,會(hui)從(cong) config server 上做(zuo)一次全(quan)量拉(la)取。對(dui)于 mongod 節(jie)點,會(hui)在內存中(zhong)維護(hu)路(lu)由(you)信(xin)息,而(er)且會(hui)在 config.cache.chunks.{ns} 表(biao)(biao)中(zhong)緩(huan)存路(lu)由(you)信(xin)息,而(er)且這個緩(huan)存路(lu)由(you)信(xin)息的表(biao)(biao)會(hui)進行主從(cong)同(tong)步。

路由(you)信息(xi)的更新整體(ti)上(shang)采(cai)用懶加載的方式。具(ju)體(ti)來說,mongos 轉發給(gei) mongod 的請(qing)求(qiu)(qiu)(qiu)會額外攜(xie)帶mongos 認(ren)為(wei)的路由(you)版(ban)本(ben)信息(xi),mongod 在收到請(qing)求(qiu)(qiu)(qiu)之(zhi)后會先進行(xing)路由(you)版(ban)本(ben)比(bi)較。如果發現有某(mou)一方的版(ban)本(ben)比(bi)較舊(jiu),則(ze)先從 config server 上(shang)拉取到最新路由(you)之(zhi)后再進行(xing)請(qing)求(qiu)(qiu)(qiu)重試。如果 2 邊的路由(you)版(ban)本(ben)一樣,則(ze)正常執行(xing)請(qing)求(qiu)(qiu)(qiu)。

Chunk 分(fen)裂

對(dui)于 4.0 及以下版(ban)本(ben),會在(zai) mongos 節點(dian)上記(ji)錄每個 chunk 的(de)寫入(ru)情況。對于 4.2 及以上版(ban)本(ben),會在(zai) mongod 節點(dian)上記(ji)錄 chunk 的(de)大小。

如果 chunk 的大小達到了設定(ding)的閾值(默認 64MB),則會觸發 chunk 分(fen)裂。分(fen)為(wei) 2 個(ge)步驟:

  1. SplitVector,確定(ding)分裂點。大致步驟(zou)為根(gen)據 shardKey 索引掃描(miao)出 chunk 的文檔條數以(yi)及平(ping)均文檔長度信息,然后將 chunk 劃(hua)分成(cheng)滿足閾值大小的多個子 chunk。
  2. SplitChunk, 執行 chunk 分裂。由(you)(you)于(yu) chunk 只是一個邏輯(ji)上的概念,因此不會涉及存儲引擎側的表(biao)(biao)變更,只會涉及到路(lu)由(you)(you)信息變更。大致流程(cheng)為(wei)將分裂出的chunk 信息提交到 config server 并刪除原先chunk 的路(lu)由(you)(you)信息,然后刷(shua)新 mongod 本地(di)的路(lu)由(you)(you)表(biao)(biao)。

Balancer 數據均衡(heng)

Config server 主(zhu)節點上(shang)會啟動一個(ge)后臺線(xian)程定期檢查(默認 2 次操作之(zhi)間間隔 10 s)分片表的(de)(de) chunks 數量(liang)在各個(ge)分片之(zhi)間是否(fou)均衡。是否(fou)均衡的(de)(de)評(ping)判標(biao)準為chunk 數量(liang)最多的(de)(de) shard 和 chunk 數量(liang)最少的(de)(de) shard 之(zhi)間的(de)(de)差值是否(fou)超(chao)過了如(ru)下閾值:

如(ru)果滿足遷(qian)移條件,則 config server 會(hui)(hui)通過 moveChunk 命令,通知(zhi) shard 之間進行 chunk 遷(qian)移。值得注意的是,chunk 數(shu)據移動不會(hui)(hui)經(jing)過 config server,只會(hui)(hui)在 shard 之間進行,config server 只會(hui)(hui)充當(dang)控(kong)制者角色。

數(shu)據遷移是非常消耗資(zi)(zi)源(yuan)的,從運營經驗來看,很多業務的請求毛刺都和數(shu)(shu)據(ju)均(jun)衡(heng)操作有關(guan)。因此,對于請求延遲敏感或資(zi)(zi)源(yuan)使(shi)用(yong)率較高的用(yong)戶,盡量使(shi)用(yong) hash 分片保(bao)證(zheng)數(shu)(shu)據(ju)分布均(jun)勻,并將數(shu)(shu)據(ju)均(jun)衡(heng)窗(chuang)口配(pei)置在(zai)業務低峰(feng)期(qi)。

使用(yong) MongoDB 分片集群的注(zhu)意事項

  1. 合(he)理(li)選擇(ze) shardKey,避免出現數據和請求傾斜的情況,避免出現 jumbo chunk ;導致負載不(bu)均。
  2. 分片(pian)集群盡(jin)量創建(jian)分片(pian)表。如(ru)果確(que)實需要(yao)創建(jian)非分片(pian)表,也盡(jin)量不要(yao)放在同一個 db 中,避(bi)免出(chu)現該 db 所在的 primary shard 數據量過大或者負載過高。
  3. 使用(yong) hash 分(fen)片(pian)時(shi),盡量使用(yong)預(yu)分(fen)片(pian)時(shi)創建(jian) initial chunks 的方式,這樣(yang)可以避免后續(xu)的 chunk 分(fen)裂和(he)遷移。
  4. 根據業務(wu)需求,配置合理的 balancer 運行窗(chuang)口,盡量(liang)避開(kai)業務(wu)高峰期。

總結

MongoDB 原生支(zhi)(zhi)持(chi)了(le)非常完(wan)善(shan)的(de)數據(ju)(ju)分片(pian)能力,通(tong)過數據(ju)(ju)分片(pian)也(ye)使得 MongoDB 在(zai)應對海量數據(ju)(ju)時游刃(ren)有余。MongoDB 支(zhi)(zhi)持(chi) range 和 hash 分片(pian)方式,并通(tong)過配(pei)置 zone 分區來進行更加(jia)靈活的(de)控制。

MongoDB 通過(guo)路由(you)版本控制(zhi)來(lai)保證路由(you)信息在多個節點上的一致性,并通過(guo) chunk 自動分裂和遷(qian)移機制(zhi)保證了(le)數據均衡。

文章來自個人專欄
文(wen)章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0