MongoDB 資料分發

來源:互聯網
上載者:User

標籤:mon   query   區別   方式   照片   大致   led   規律   固定   

在MongoDB(版本 3.2.9)中,資料的分發是指將collection的資料拆分成塊(chunk),分布到不同的分區(shard)上,資料分發主要有2種方式:基於資料區塊(chunk)數量的均衡分發和基於片鍵範圍(range)的定向分發。MongoDB內建均衡器(balancer),用於拆分塊和移動塊,自動實現資料區塊在不同shard上的均勻分布。balancer只保證每個shard上的chunk數量大致相同,不保證每個shard上的doc數量大致相同。

一,資料按照chunk數量進行均衡分發

均衡分發是MongoDB自動實現的,使資料庫結構描述對Application透明,簡化系統的管理,使得向分區叢集中增減分區變得容易。均衡分發是由MongoDB內建均衡器(balancer)來實現的,Balancer按照collection的索引欄位來進行資料分發,該欄位叫做片鍵(sharded key)。片鍵一般有三種類型:升序片鍵,隨機片鍵和基於分組的片鍵。

塊(chunk)是由多個doc組成的一個分組,在某個索引欄位(片鍵)上是連續的,每個chunk的片鍵是有一定範圍的。塊的預設大小是64MB。有些chunk會非常大,包含的doc數量非常多,但是,在MongoDB看來,仍然是一個chunk,和沒有任何doc的空chunk沒有區別。均衡分發保證每個shard的chunk數量是大致相同的。因此,片鍵的選擇直接影響分區的好壞。

例如:一個MongoDB分區叢集有3個shard,分別是shard1,shar2,shard3。片鍵的最小值是:$MinKey,最大值是:$MaxKey。包含端值$MinKey的chunk是最小塊,包含端值$MaxKey的chunk是最大塊。

1,升序片鍵

升序片鍵類似date欄位或者_id欄位,是一種隨著時間穩定增長的欄位。假如分區的欄位是_id欄位,集合foo中存在10個doc,每個shard中存在一個資料區塊,分別是:chunk1:$MinKey-3,chunk2:4-8,chunk3:9-$MaxKey。

使用升序片鍵的劣勢是:每次插入一個新的doc,都會插入到最大塊中,這會導致所有的寫請求都會被路由到同一個分區,導致最大塊不斷增長,不斷被拆分,然後不斷被移動到其他分區中,導致資料的寫入不均衡,塊移動會額外增加Disk的寫數量。使用升序片鍵的優勢是:按照片鍵進行範圍讀時,效能高。

2,隨機片鍵

隨機片鍵是指片鍵的值不是固定增長,而是一些沒有規律的索引值。由於寫入資料是隨機分發的,各分區增長的速度大致相同,減少了chunk 遷移的次數。使用隨機分區的弊端是:寫入的位置是隨機的,如果使用Hash Index來產生隨機值,那麼範圍查詢的速度會很慢。

3,基於分組的片鍵

基於分組的片鍵是兩欄位的複合片鍵,第一個欄位用於分組,該欄位的勢最好是比較低的,勢是在同一欄位中不同值(distinct value)的數量或所佔的比例;第二個欄位用於自增,該欄位最好是自增欄位。這種片鍵策略是最好的,能夠實現多熱點資料的讀寫。

單個mongod 在處理升序寫請求時是最有效,資料只需要寫入到集合的末尾。基於分組的片鍵,將數量不多的分組分布在分區叢集中,每個shard只有少量的chunk,這樣能夠將資料的寫操作分布在分區叢集中的每個shard上,在單個shard上,以升序方式讀寫資料。一個shard上的分組太多,寫請求就相當於隨機寫了,反而不好。

二,按照片鍵範圍進行定向分發

如果希望特定範圍的chunk被分發到特定的分區中,可以為分區添加tag,然後為tag指定相應的片鍵範圍,這樣,如果一個doc屬於tag的片鍵範圍,就會被定向到特定的shard中。

1,為shard指定tag

sh.addShardTag("shar1","shard_tag1");sh.addShardTag("shar2","shard_tag2");sh.addShardTag("shar3","shard_tag2");

2,為tag指定片鍵範圍

sh.addTagRange(    "db_name.collection_name",    {field:"min_value"},    {field:"max_value"},     "shard_tag")

每個shard的tag可以使用任意數量的tag,MongoDB的均衡器在移動塊時,會將特定片鍵範圍的chunk移動到特定的shard上。
三,手動進行資料的分發

MongoDB內建均衡器(balancer),自動實現資料區塊的拆分和移動,有時,可以關閉balancer,使用moveChunk命令手動移動資料區塊。

1,關閉balancer

串連到一個mongos,更新config.setting命名空間

use config
db.setting.update({"_id":"balancer"},{"enabled":false},true)

--or
sh.setBalancerState(false);

2,拆分塊
拆分塊是指新增一個邊界點,將一個chunk在邊界點處拆分成兩個chunk。在MongoDB中,將片鍵從小到大排序,邊界值屬於右邊的chunk。

sh.splitAt("db_name.collection_name",{sharded_filed:"new_boundary_value"})

3,移動塊
MongoDB將包含指定文檔的chunk移動到指定的shard上,必須使用片鍵來尋找所要一定的chunk。

sh.moveChunk("db_name.collection_name",{sharded_filed:"value_in_chunk"},"new_shard_name")

4,啟用balancer

sh.setBalancerState(true)

5,重新整理mongos的緩衝

在Application layer 和資料存放區之間,存在一個Query Router,即mongos,mongos會在第一次啟動或分區的中繼資料被更新之後,從config server 同步配置資料,並緩衝在mongos中。有時,mongos無法從config server上及時同步最新的配置資訊,導致無法路由到相應的chunk,不能返回正確的資料,可以使用flushRouterConfig 命令手動重新整理mongos的緩衝

db.adminCommand({"flushRouterConfig":1})

 

參考文檔:

Sharding

MongoDB 資料分發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.