將存儲在MongoDB數(shù)據(jù)庫中的Collection進(jìn)行分片需要選定分片Key(Shard key),對于分片Key的選定直接決定了集群中數(shù)據(jù)分布是否均衡、集群性能是否合理。那么我們究竟該選擇什么樣的字段來作為分片Key呢?有如下幾個需要考慮點(diǎn)。 以下述記錄日志的Document為例: { server : "ny153.example.com" , application : "apache" , time : "2011-01-02T21:21:56.249Z" , level : "ERROR" , msg : "something is broken" } 基數(shù) Mongodb中一個被分片的Collection的所有數(shù)據(jù)都存放在眾多的Chunk中。一個Chunk存放分片字段的一個區(qū)間范圍的數(shù)據(jù)。選擇一個好的分片字段非常重要,否則就會遭遇到不能被拆分的大Chunk。 用上述的日志為例,如果選擇{server:1}來作為一個分片Key的話,一個server上的所有數(shù)據(jù)都是在同一個Chunk中,很容易想到一個Server上的日志數(shù)據(jù)會超過200MB(默認(rèn)Chunk大?。?。如果分片Key是{server:1,time:1},那么能夠?qū)⒁粋€Server上的日志信息進(jìn)行分片,直至毫秒級別,絕對不會存在不可被拆分的Chunk。 將Chunk的規(guī)模維持在一個合理的大小是非常重要的,只有這樣數(shù)據(jù)才能均勻分布,并且移動Chunk的代價也不會過大。 寫操作可擴(kuò)展 使用分片的一個主要原因之一是分散寫操作。為了實(shí)現(xiàn)這個目標(biāo),盡可能的將寫操作分散到多個Chunk就尤為重要了。 用上述的日志實(shí)例,選擇{time:1}來作為分片key將導(dǎo)致所有的寫操作都會落在最新的一個Chunk上去,這樣就形成了一個熱點(diǎn)區(qū)域。如果選擇{server:1,application:1,time:1}來作為分片Key的話,那么每一個Server上的應(yīng)用的日志信息將會寫在不同的地方,如果有100個Server和應(yīng)用對,有10臺Server,那么每一臺Server將會分擔(dān)1/10的寫操作。 查詢隔離 另外一個需要考慮的是任何一個查詢操作將會由多少個分片來來提供服務(wù)。最理想的情況是,一個查詢操作直接從Mongos進(jìn)程路由到一個Mongodb上去,并且這個Mongodb擁有該次查詢的全部數(shù)據(jù)。因此,如果你知道最為通用的查詢操作的都以server作為一個查詢條件的話,以Server作為一個起始的分片Key會使整個集群更加高效。 任何一個查詢都能執(zhí)行,不管使用什么來作為分片Key,但是,如果Mongos進(jìn)程不知道是哪一個Mongodb的分片擁有要查詢的數(shù)據(jù)的話,Mongos將會讓所有的Mongod分片去執(zhí)行查詢操作,再將結(jié)果信息匯總起來返回。顯而易見,這回增加服務(wù)器的響應(yīng)時間,會增加網(wǎng)絡(luò)成本,也會無謂的增加了Load。 排序 在需要調(diào)用sort()來查詢排序后的結(jié)果的時候,以分片Key的最左邊的字段為依據(jù),Mongos可以按照預(yù)先排序的結(jié)果來查詢最少的分片,并且將結(jié)果信息返回給調(diào)用者。這樣會花最少的時間和資源代價。 相反,如果在利用sort()來排序的時候,排序所依據(jù)的字段不是最左側(cè)(起始)的分片Key,那么Mongos將不得不并行的將查詢請求傳遞給每一個分片,然后將各個分片返回的結(jié)果合并之后再返回請求方。這個會增加Mongos的額外的負(fù)擔(dān)。 可靠性 選擇分片Key的一個非常重要因素是萬一某一個分片徹底不可訪問了,受到影響的Chunk有多大(即使是用貌似可以信賴的Replica Set)。 假定,有一個類似于Twiter的系統(tǒng),Comment記錄類似如下形式: { _id: ObjectId("4d084f78a4c8707815a601d7"), user_id : 42 , time : "2011-01-02T21:21:56.249Z" , comment : "I am happily using MongoDB", } 由于這個系統(tǒng)對寫操作非常敏感,所以需要將寫操作扁平化的分布到所有的Server上去,這個時候就需要用id或者user_id來作為分片Key了。使用Id作為分片Key有最大粒度的扁平化,但是在一個分片宕機(jī)的情況下,會影響幾乎所有的用戶(一些數(shù)據(jù)丟失了)。如果使用User_id作為分片Key,只有極少比率的用戶會收到影響(在存在5個分片的時候,20%的用戶受影響),但是這些用戶會再也不會看到他們的數(shù)據(jù)了。 索引優(yōu)化 正如在別的章節(jié)中提到索引的一樣,如果只有一部分的索引被讀或者更新的話,通常會有更好的性能,因?yàn)椤盎钴S”的部分在大多數(shù)時間內(nèi)能駐留在內(nèi)存中。本文上述的所描述的選擇分片Key的方法都是為了最終數(shù)據(jù)能夠均勻的分布,與此同時,每一個Mongod的索引信息也被均勻分布了。相反,使用時間戳作為分片key的起始字段會有利于將常用索引限定在較小的一部分。 假定有一個圖片存儲系統(tǒng),圖片記錄類似于如下形式: { _id: ObjectId("4d084f78a4c8707815a601d7"), user_id : 42 , title: "sunset at the beach", upload_time : "2011-01-02T21:21:56.249Z" , data: ..., } 你也能構(gòu)造一個客戶id,讓它包括圖片上傳時間對應(yīng)的月度信息和一個唯一標(biāo)志符(ObjectID,數(shù)據(jù)的MD5等)。記錄看起來就像下面這個樣子的: { _id: "2011-01-02_4d084f78a4c8707815a601d7", user_id : 42 , title: "sunset at the beach", upload_time : "2011-01-02T21:21:56.249Z" , data: ..., } 客戶id作為分片key,并且這個id也被用于去訪問這個Document。即能將數(shù)據(jù)均衡的分布在各個節(jié)點(diǎn)上,也減少了大多數(shù)查詢所使用的索引比例。 更進(jìn)一步來講: 在每一個月份的開始,在開最初的一段時間內(nèi)只有一個Server來存取數(shù)據(jù),隨著數(shù)據(jù)量的增長,負(fù)載均衡器(balancer)就開始進(jìn)行分裂和遷移數(shù)據(jù)塊了。為了避免潛在的低效率和遷移數(shù)據(jù),預(yù)先創(chuàng)建分片范圍區(qū)間是明智之舉。(如果有5個Sever則分5個區(qū)間) 可以繼續(xù)改進(jìn),可以把User_ID包含到圖片的id中來。這樣的話會讓一個用戶的所有Document都在一個分片上。比如用“2011-01-02_42_4d084f78a4c8707815a601d7”作為圖片的id。 GridFS 根據(jù)需求的不同,GridFS有幾種不同的分片方法?;陬A(yù)先存在的索引是慣用的分片辦法: 1)“files”集合(Collection)不會分片,所有的文件記錄都會位于一個分片上,高度推薦使該分片保持高度靈活(至少使用由3個節(jié)點(diǎn)構(gòu)成的replica set)。 2)“chunks”集合(Collection)應(yīng)該被分片,并且用索引”files_id:1”。已經(jīng)存在的由MongoDB的驅(qū)動來創(chuàng)建的“files_id,n”索引不能用作分片Key(這個是一個分片約束,后續(xù)會被修復(fù)),所以不得不創(chuàng)建一個獨(dú)立的”files_id”索引。使用“files_id”作為分片Key的原因是一個特定的文件的所有Chunks都是在相同的分片上,非常安全并且允許運(yùn)行“filemd5”命令(要求特定的驅(qū)動)。 運(yùn)行如下命令: > db.fs.chunks.ensureIndex({files_id: 1}); > db.runCommand({ shardcollection : "test.fs.chunks", key : { files_id : 1 }}) { "collectionsharded" : "test.fs.chunks", "ok" : 1 } 由于默認(rèn)的files_id是一個ObjectId,files_id將會升序增長,因此,GridFS的全部Chunks都會被從一個單點(diǎn)分片上存取。如果寫的負(fù)載比較高,就需要使用其他的分片Key了,或者使用其它的值(_id)來作為分片Key了。
選擇分片Key的需要考慮的因素具有一定的對立性,不可能樣樣的具備,在實(shí)際使用過程中還是需要根據(jù)需求的不同來進(jìn)行權(quán)衡,適當(dāng)放棄一些。沒有萬能的普適分片辦法,需求才是王道。 |
|
來自: CevenCheng > 《分片》