MongoDB中shard key的選擇

來源:互聯網
上載者:User

將儲存在MongoDB資料庫中的Collection進行分區需要選定分區Key(Shard key),對於分區Key的選定直接決定了叢集中資料分布是否均衡、叢集效能是否合理。那麼我們究竟該選擇什麼樣的欄位來作為分區Key呢?有如下幾個需要考慮點。

以下述記錄日誌的Document為例:

{

server : "ny153.example.com" ,

application : "apache" ,

time : "2011-01-02T21:21:56.249Z" ,

level : "ERROR" ,

msg : "something is broken"

}

基數

Mongodb中一個被分區的Collection的所有資料都存放在眾多的Chunk中。一個Chunk存放分區欄位的一個區間範圍的資料。選擇一個好的分區欄位非常重要,否則就會遭遇到不能被拆分的大Chunk。

用上述的日誌為例,如果選擇{server:1}來作為一個分區Key的話,一個server上的所有資料都是在同一個Chunk中,很容易想到一個Server上的日誌資料會超過200MB(預設Chunk大小)。如果分區Key是{server:1,time:1},那麼能夠將一個Server上的日誌資訊進行分區,直至毫秒層級,絕對不會存在不可被拆分的Chunk。

將Chunk的規模維持在一個合理的大小是非常重要的,只有這樣資料才能均勻分布,並且移動Chunk的代價也不會過大。

寫操作可擴充

使用分區的一個主要原因之一是分散寫操作。為了實現這個目標,儘可能的將寫操作分散到多個Chunk就尤為重要了。

用上述的日誌執行個體,選擇{time:1}來作為分區key將導致所有的寫操作都會落在最新的一個Chunk上去,這樣就形成了一個作用區。如果選擇{server:1,application:1,time:1}來作為分區Key的話,那麼每一個Server上的應用的日誌資訊將會寫在不同的地方,如果有100個Server和應用對,有10台Server,那麼每一台Server將會分擔1/10的寫操作。

查詢隔離

另外一個需要考慮的是任何一個查詢操作將會由多少個分區來來提供服務。最理想的情況是,一個查詢操作直接從Mongos進程路由到一個Mongodb上去,並且這個Mongodb擁有該次查詢的全部資料。因此,如果你知道最為通用的查詢操作的都以server作為一個查詢條件的話,以Server作為一個起始的分區Key會使整個叢集更加高效。

任何一個查詢都能執行,不管使用什麼來作為分區Key,但是,如果Mongos進程不知道是哪一個Mongodb的分區擁有要查詢的資料的話,Mongos將會讓所有的Mongod分區去執行查詢操作,再將結果資訊匯總起來返回。顯而易見,這回增加伺服器的回應時間,會增加網路成本,也會無謂的增加了Load。

排序

在需要調用sort()來查詢排序後的結果的時候,以分區Key的最左邊的欄位為依據,Mongos可以按照預先排序的結果來查詢最少的分區,並且將結果資訊返回給調用者。這樣會花最少的時間和資源代價。

相反,如果在利用sort()來排序的時候,排序所依據的欄位不是最左側(起始)的分區Key,那麼Mongos將不得不並行的將查詢請求傳遞給每一個分區,然後將各個分區返回的結果合并之後再返回請求方。這個會增加Mongos的額外的負擔。

可靠性

選擇分區Key的一個非常重要因素是萬一某一個分區徹底不可訪問了,受到影響的Chunk有多大(即使是用貌似可以信賴的Replica Set)。

假定,有一個類似於Twiter的系統,Comment記錄類似如下形式:

{

_id: ObjectId("4d084f78a4c8707815a601d7"),

user_id : 42 ,

time : "2011-01-02T21:21:56.249Z" ,

comment : "I am happily using MongoDB",

}

由於這個系統對寫操作非常敏感,所以需要將寫操作扁平化的分布到所有的Server上去,這個時候就需要用id或者user_id來作為分區Key了。使用Id作為分區Key有最大粒度的扁平化,但是在一個分區宕機的情況下,會影響幾乎所有的使用者(一些資料丟失了)。如果使用User_id作為分區Key,只有極少比率的使用者會收到影響(在存在5個分區的時候,20%的使用者受影響),但是這些使用者會再也不會看到他們的資料了。

索引最佳化

正如在別的章節中提到索引的一樣,如果只有一部分的索引被讀或者更新的話,通常會有更好的效能,因為“活躍”的部分在大多數時間內能駐留在記憶體中。本文上述的所描述的選擇分區Key的方法都是為了最終資料能夠均勻的分布,與此同時,每一個Mongod的索引資訊也被均勻分布了。相反,使用時間戳作為分區key的起始欄位會有利於將常用索引限定在較小的一部分。

假定有一個圖片儲存系統,圖片記錄類似於如下形式:

{

_id: ObjectId("4d084f78a4c8707815a601d7"),

user_id : 42 ,

title: "sunset at the beach",

upload_time : "2011-01-02T21:21:56.249Z" ,

data: ...,

}

你也能構造一個客戶id,讓它包括圖片上傳時間對應的月度資訊和一個唯一標誌符(ObjectID,資料的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。即能將資料均衡的分布在各個節點上,也減少了大多數查詢所使用的索引比例。

更進一步來講:

在每一個月份的開始,在開最初的一段時間內只有一個Server來存取資料,隨著資料量的增長,負載平衡器(balancer)就開始進行分裂和遷移資料區塊了。為了避免潛在的低效率和遷移資料,預先建立分區範圍區間是明智之舉。(如果有5個Sever則分5個區間)

可以繼續改進,可以把User_ID包含到圖片的id中來。這樣的話會讓一個使用者的所有Document都在一個分區上。比如用“2011-01-02_42_4d084f78a4c8707815a601d7”作為圖片的id。

GridFS

根據需求的不同,GridFS有幾種不同的分區方法。基於預先存在的索引是慣用的分區辦法:

1)“files”集合(Collection)不會分區,所有的檔案記錄都會位於一個分區上,高度推薦使該分區保持高度靈活(至少使用由3個節點構成的replica set)。

2)“chunks”集合(Collection)應該被分區,並且用索引”files_id:1”。已經存在的由MongoDB的驅動來建立的“files_id,n”索引不能用作分區Key(這個是一個分區約束,後續會被修複),所以不得不建立一個獨立的”files_id”索引。使用“files_id”作為分區Key的原因是一個特定的檔案的所有Chunks都是在相同的分區上,非常安全並且允許運行“filemd5”命令(要求特定的驅動)。

運行如下命令:

> db.fs.chunks.ensureIndex({files_id: 1});

> db.runCommand({ shardcollection : "test.fs.chunks", key : { files_id : 1 }})

{ "collectionsharded" : "test.fs.chunks", "ok" : 1 }

由於預設的files_id是一個ObjectId,files_id將會升序增長,因此,GridFS的全部Chunks都會被從一個單點分區上存取。如果寫的負載比較高,就需要使用其他的分區Key了,或者使用其它的值(_id)來作為分區Key了。

選擇分區Key的需要考慮的因素具有一定的對立性,不可能樣樣的具備,在實際使用過程中還是需要根據需求的不同來進行權衡,適當放棄一些。沒有萬能的普適分區辦法,需求才是王道。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.