MongoDB之 Sharded cluster架構(gòu)原理

MongoDB之 Sharded cluster架構(gòu)原理

為什么需要Sharded cluster跋理?

MongoDB目前3大核心優(yōu)勢:『靈活模式』+ 『高可用性』 + 『可擴展性』拜效,通過json文檔來實現(xiàn)靈活模式,通過復(fù)制集(https://yq.aliyun.com/articles/64?spm=0.0.0.0.9jrPm8)來保證高可用拭荤,通過Sharded cluster來保證可擴展性。

當(dāng)MongoDB復(fù)制集遇到下面的業(yè)務(wù)場景時秘蛔,你就需要考慮使用Sharded cluster

●存儲容量需求超出單機磁盤容量

●活躍的數(shù)據(jù)集超出單機內(nèi)存容量糠排,導(dǎo)致很多請求都要從磁盤讀取數(shù)據(jù),影響性能

●寫IOPS超出單個MongoDB節(jié)點的寫服務(wù)能力

如上圖所示蠢壹,Sharding Cluster使得集合的數(shù)據(jù)可以分散到多個Shard(復(fù)制集或者單個Mongod節(jié)點)存儲嗓违,使得MongoDB具備了橫向擴展(Scale out)的能力,豐富了MongoDB的應(yīng)用場景图贸。

Sharded cluster架構(gòu)

Sharded cluster由Shard蹂季、Mongos和Config server 3個組件構(gòu)成冕广。

Mongos是Sharded cluster的訪問入口,強烈建議所有的管理操作偿洁、讀寫操作都通過mongos來完成撒汉,以保證cluster多個組件處于一致的狀態(tài)。

Mongos本身并不持久化數(shù)據(jù)涕滋,Sharded cluster所有的元數(shù)據(jù)都會存儲到Config Server(下一節(jié)詳細介紹)睬辐,而用戶的數(shù)據(jù)則會分散存儲到各個shard。Mongos啟動后宾肺,會從config server加載元數(shù)據(jù)溯饵,開始提供服務(wù),將用戶的請求正確路由到對應(yīng)的Shard锨用。

數(shù)據(jù)分布策略

Sharded cluster支持將單個集合的數(shù)據(jù)分散存儲在多個shard上丰刊,用戶可以指定根據(jù)集合內(nèi)文檔的某個字段即shard key來分布數(shù)據(jù),目前主要支持2種數(shù)據(jù)分布的策略增拥,范圍分片(Range based sharding)或hash分片(Hash based sharding)啄巧。

范圍分片

如上圖所示,集合根據(jù)x字段來分片跪者,x的取值范圍為[minKey, maxKey](x為整型棵帽,這里的minKey、maxKey為整型的最小值和最大值)渣玲,將整個取值范圍劃分為多個chunk,每個chunk(通常配置為64MB)包含其中一小段的數(shù)據(jù)弟晚。

Chunk1包含x的取值在[minKey, -75)的所有文檔忘衍,而Chunk2包含x取值在[-75, 25)之間的所有文檔… 每個chunk的數(shù)據(jù)都存儲在同一個Shard上,每個Shard可以存儲很多個chunk卿城,chunk存儲在哪個shard的信息會存儲在Config server種枚钓,mongos也會根據(jù)各個shard上的chunk的數(shù)量來自動做負載均衡。

范圍分片能很好的滿足『范圍查詢』的需求瑟押,比如想查詢x的值在[-30, 10]之間的所有文檔搀捷,這時mongos直接能將請求路由到Chunk2,就能查詢出所有符合條件的文檔多望。

范圍分片的缺點在于嫩舟,如果shardkey有明顯遞增(或者遞減)趨勢,則新插入的文檔多會分布到同一個chunk怀偷,無法擴展寫的能力家厌,比如使用_id作為shard key,而MongoDB自動生成的id高位是時間戳椎工,是持續(xù)遞增的饭于。

Hash分片

Hash分片是根據(jù)用戶的shard key計算hash值(64bit整型)蜀踏,根據(jù)hash值按照『范圍分片』的策略將文檔分布到不同的chunk。

Hash分片與范圍分片互補掰吕,能將文檔隨機的分散到各個chunk果覆,充分的擴展寫能力,彌補了范圍分片的不足殖熟,但不能高效的服務(wù)范圍查詢局待,所有的范圍查詢要分發(fā)到后端所有的Shard才能找出滿足條件的文檔。

合理的選擇shard key

選擇shard key時吗讶,要根據(jù)業(yè)務(wù)的需求及『范圍分片』和『Hash分片』2種方式的優(yōu)缺點合理選擇燎猛,同時還要注意shard key的取值一定要足夠多,否則會出現(xiàn)單個jumbo chunk照皆,即單個chunk非常大并且無法分裂(split)重绷;比如某集合存儲用戶的信息,按照age字段分片膜毁,而age的取值非常有限昭卓,必定會導(dǎo)致單個chunk非常大。

Mongos

Mongos作為Sharded cluster的訪問入口瘟滨,所有的請求都由mongos來路由候醒、分發(fā)、合并杂瘸,這些動作對客戶端driver透明倒淫,用戶連接mongos就像連接mongod一樣使用。

Mongos會根據(jù)請求類型及shard key將請求路由到對應(yīng)的Shard

查詢請求

●查詢請求不包含shard key败玉,則必須將查詢分發(fā)到所有的shard敌土,然后合并查詢結(jié)果返回給客戶端

●查詢請求包含shard key,則直接根據(jù)shard key計算出需要查詢的chunk运翼,向?qū)?yīng)的shard發(fā)送查詢請求

寫請求

寫操作必須包含shard key返干,mongos根據(jù)shard key算出文檔應(yīng)該存儲到哪個chunk,然后將寫請求發(fā)送到chunk所在的shard血淌。

更新/刪除請求

更新矩欠、刪除請求的查詢條件必須包含shard key或者_id,如果是包含shard key悠夯,則直接路由到指定的chunk癌淮,如果只包含_id,則需將請求發(fā)送至所有的shard疗疟。

其他命令請求

除增刪改查外的其他命令請求處理方式都不盡相同该默,有各自的處理邏輯,比如listDatabases命令策彤,會向每個Shard及Config Server轉(zhuǎn)發(fā)listDatabases請求栓袖,然后將結(jié)果進行合并匣摘。

Config Server

config database

Config server存儲Sharded cluster的所有元數(shù)據(jù),所有的元數(shù)據(jù)都存儲在config數(shù)據(jù)庫裹刮,3.2版本后音榜,Config Server可部署為一個獨立的復(fù)制集,極大的方便了Sharded cluster的運維管理捧弃。

mongos> use config

switched to db config

mongos> db.getCollectionNames()

[

"shards",

"actionlog",

"chunks",

"mongos",

"collections",

"lockpings",

"settings",

"version",

"locks",

"databases",

"tags",

"changelog"

]

config.shards

config.shards集合存儲各個Shard的信息赠叼,可通過addShard、removeShard命令來動態(tài)的從Sharded cluster里增加或移除shard违霞。如下所示嘴办,cluster目前擁有2個shard,均為復(fù)制集买鸽。

mongos> db.addShard("mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003")

mongos> db.addShard("mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003")

mongos> db.shards.find()

{ "_id" : "mongo-9003", "host" : "mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003" }

{ "_id" : "mongo-9004", "host" : "mongo-9004/10.1.72.135:9004,10.1.72.136:9004,10.1.72.137:9004" }

config.databases

config.databases集合存儲所有數(shù)據(jù)庫的信息涧郊,包括DB是否開啟分片,primary shard信息眼五,對于數(shù)據(jù)庫內(nèi)沒有開啟分片的集合妆艘,所有的數(shù)據(jù)都會存儲在數(shù)據(jù)庫的primary shard上。

如下所示看幼,shtest數(shù)據(jù)庫是開啟分片的(通過enableSharding命令)批旺,primary shard為mongo-9003; 而test數(shù)據(jù)庫沒有開啟分片诵姜,primary shard為mongo-9003汽煮。

mongos> sh.enableSharding("shtest") { "ok" : 1 }

mongos> db.databases.find()

{ "_id" : "shtest", "primary" : "mongo-9003", "partitioned" : true }

{ "_id" : "test", "primary" : "mongo-9003", "partitioned" : false }

Sharded cluster在數(shù)據(jù)庫創(chuàng)建時,為用戶選擇當(dāng)前存儲數(shù)據(jù)量最小的shard作為數(shù)據(jù)庫的primary shard棚唆,用戶也可調(diào)用movePrimary命令來改變primary shard以實現(xiàn)負載均衡逗物,一旦primary shard發(fā)生改變,mongos會自動將數(shù)據(jù)遷移到的新的primary shard上瑟俭。

config.colletions

數(shù)據(jù)分片是針對集合維度的,某個數(shù)據(jù)庫開啟分片功能后契邀,如果需要讓其中的集合分片存儲摆寄,則需調(diào)用shardCollection命令來針對集合開啟分片。

如下命令坯门,針對shtest數(shù)據(jù)里的hello集合開啟分片微饥,使用x字段作為shard key來進行范圍分片。

mongos> sh.shardCollection("shtest.coll", {x: 1})

{ "collectionsharded" : "shtest.coll", "ok" : 1 }

mongos> db.collections.find()

{ "_id" : "shtest.coll", "lastmodEpoch" : ObjectId("57175142c34046c3b556d302"), "lastmod" : ISODate("1970-02-19T17:02:47.296Z"), "dropped" : false, "key" : { "x" : 1 }, "unique" : false }

config.chunks

集合分片開啟后古戴,默認會創(chuàng)建一個新的chunk欠橘,shard key取值[minKey, maxKey]內(nèi)的文檔(即所有的文檔)都會存儲到這個chunk。當(dāng)使用Hash分片策略時现恼,可以預(yù)先創(chuàng)建多個chunk肃续,以減少chunk的遷移黍檩。

mongos> db.chunks.find({ns: "shtest.coll"})

{ "_id" : "shtest.coll-x_MinKey", "ns" : "shtest.coll", "min" : { "x" : { "$minKey" : 1 } }, "max" : { "x" : { "$maxKey" : 1 } }, "shard" : "mongo-9003", "lastmod" : Timestamp(1, 0), "lastmodEpoch" : ObjectId("5717530fc34046c3b556d361") }

當(dāng)chunk里寫入的數(shù)據(jù)量增加到一定閾值時,會觸發(fā)chunk分裂始锚,將一個chunk的范圍分裂為多個chunk刽酱,當(dāng)各個shard上chunk數(shù)量不均衡時,會觸發(fā)chunk在shard間的遷移瞧捌。如下所示棵里,shtest.coll的一個chunk,在寫入數(shù)據(jù)后分裂成3個chunk姐呐。

mongos> use shtest

mongos> for (var i = 0; i < 10000; i++) { db.coll.insert( {x: i} ); }

mongos> use config

mongos> db.chunks.find({ns: "shtest.coll"})

{ "_id" : "shtest.coll-x_MinKey", "lastmod" : Timestamp(5, 1), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : { "$minKey" : 1 } }, "max" : { "x" : 1 }, "shard" : "mongo-9003" }

{ "_id" : "shtest.coll-x_1.0", "lastmod" : Timestamp(4, 0), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : 1 }, "max" : { "x" : 31 }, "shard" : "mongo-9003" }

{ "_id" : "shtest.coll-x_31.0", "lastmod" : Timestamp(5, 0), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : 31 }, "max" : { "x" : { "$maxKey" : 1 } }, "shard" : "mongo-9004" }

config.settings

config.settings集合里主要存儲sharded cluster的配置信息殿怜,比如chunk size,是否開啟balancer等

mongos> db.settings.find()

{ "_id" : "chunksize", "value" : NumberLong(64) }

{ "_id" : "balancer", "stopped" : false }

其他集合

●config.tags主要存儲sharding cluster標簽(tag)相關(guān)的你洗曙砂,以實現(xiàn)根據(jù)tag來分布chunk的功能头谜;

●config.changelog主要存儲sharding cluster里的所有變更操作,比如balancer遷移chunk的動作就會記錄到changelog里麦轰;

●config.mongos存儲當(dāng)前集群所有mongos的信息乔夯;

●config.locks存儲鎖相關(guān)的信息,對某個集合進行操作時款侵,比如moveChunk末荐,需要先獲取鎖,避免多個mongos同時遷移同一個集合的chunk新锈。

來源:數(shù)據(jù)庫內(nèi)核月報

原文:http://mysql.taobao.org/monthly/2016/05/08/

如有侵權(quán)或不周之處甲脏,敬請勞煩聯(lián)系若飛(微信:1321113940)馬上刪除,謝謝妹笆!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末块请,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拳缠,更是在濱河造成了極大的恐慌墩新,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窟坐,死亡現(xiàn)場離奇詭異海渊,居然都是意外死亡,警方通過查閱死者的電腦和手機哲鸳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門臣疑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人徙菠,你說我怎么就攤上這事讯沈。” “怎么了婿奔?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵缺狠,是天一觀的道長问慎。 經(jīng)常有香客問我,道長儒老,這世上最難降的妖魔是什么蝴乔? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮驮樊,結(jié)果婚禮上薇正,老公的妹妹穿的比我還像新娘。我一直安慰自己囚衔,他們只是感情好挖腰,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著练湿,像睡著了一般猴仑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肥哎,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天辽俗,我揣著相機與錄音,去河邊找鬼篡诽。 笑死崖飘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的杈女。 我是一名探鬼主播朱浴,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼达椰!你這毒婦竟也來了翰蠢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤啰劲,失蹤者是張志新(化名)和其女友劉穎梁沧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝇裤,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡趁尼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猖辫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡砚殿,死狀恐怖啃憎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情似炎,我是刑警寧澤辛萍,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布悯姊,位于F島的核電站,受9級特大地震影響贩毕,放射性物質(zhì)發(fā)生泄漏悯许。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一辉阶、第九天 我趴在偏房一處隱蔽的房頂上張望先壕。 院中可真熱鬧,春花似錦谆甜、人聲如沸垃僚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谆棺。三九已至,卻和暖如春罕袋,著一層夾襖步出監(jiān)牢的瞬間改淑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工浴讯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朵夏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓兰珍,卻偏偏與公主長得像侍郭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子掠河,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容