1. 程式人生 > >MongoDB 分片管理

MongoDB 分片管理

Mongodb版本:3.6 

一、分片概念

1.資料塊

塊也叫區間,可能存在一分片一區間和一分片多區間兩種情況。

一分片一區間:資料不會在片之間自動移動來保持分片的資料的均勻性,需要手動拆分分片來移動資料。

而一分片多區間情況:一個數據塊預設64MB,當資料塊達到64MB時就會建立新的塊,當然前提是當前的粒度還允許再拆分,平衡器會保證每個分片資料塊的均勻。但是移動塊也遵循分片的原則,塊之間的資料集不能有交集。

比如一個塊[50-100)現在拆分成兩個塊,那麼預設會拆分成[50-75)[75-100)兩個塊,如果當前分片塊比其它分片的塊大於9那麼可能[75-100)改塊會被移動到新的分片當中。

2.平衡器

平衡器(balancer)負責資料的遷移。它會週期性地檢查分片間是否存在不平衡,如果存在,則會開啟塊的遷移。不平衡的表現指,一個分片明顯比其他分片擁有更多的塊。假如有一些集合達到了閾值,平衡器則會開始做塊遷移。它會從負載比較比較大的分片中選擇一個塊,並詢問該分片是否需要在遷移之前對塊進行拆分。完成必要的拆分後,就會將塊遷移至數量比較少的機器上。

二、分片查詢

1.查詢群集狀態

sh.status

需要顯示隱藏的分片資訊執行

sh.status(true)

2.檢查配置資訊

所有的配置資訊都儲存在配置伺服器的config資料庫中。

use config

show tables

actionlog

記錄平衡器的相關操作日誌。

changelog

跟蹤記錄叢集的操作,包括集合分片操作、塊拆分和遷移、新增刪除分片等。例如塊拆分資訊:

db.getCollection('changelog').find({"what":/split/}).sort({"time":-1}).limit(2)

每次資料庫塊移動都會建立插入4條記錄到changelog文件總,分別是start、commit、from、to

{

    "_id" : "backup-2018-04-09T15:52:26.656+0800-5acb1bbaebfa528b3521327c
", "server" : "backup", "clientAddr" : "192.168.137.30:53996", "time" : ISODate("2018-04-09T07:52:26.656Z"), "what" : "moveChunk.start", "ns" : "test.person", "details" : { "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : 1.0 }, "from" : "rs-b", "to" : "rs-a" } } /* 2 */ { "_id" : "backup-2018-04-09T15:52:29.289+0800-5acb1bbdebfa528b35213335", "server" : "backup", "clientAddr" : "192.168.137.30:53996", "time" : ISODate("2018-04-09T07:52:29.289Z"), "what" : "moveChunk.commit", "ns" : "test.person", "details" : { "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : 1.0 }, "from" : "rs-b", "to" : "rs-a" } } /* 3 */ { "_id" : "backup-2018-04-09T15:52:29.297+0800-5acb1bbdebfa528b3521333a", "server" : "backup", "clientAddr" : "192.168.137.30:53996", "time" : ISODate("2018-04-09T07:52:29.297Z"), "what" : "moveChunk.from", "ns" : "test.person", "details" : { "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : 1.0 }, "step 1 of 6" : 0, "step 2 of 6" : 10, "step 3 of 6" : 153, "step 4 of 6" : 2061, "step 5 of 6" : 402, "step 6 of 6" : 24, "to" : "rs-a", "from" : "rs-b", "note" : "success" } } /* 4 */ { "_id" : "master-2018-04-09T15:52:29.307+0800-5acb1bbd7bc60438ea626411", "server" : "master", "clientAddr" : "", "time" : ISODate("2018-04-09T07:52:29.307Z"), "what" : "moveChunk.to", "ns" : "test.person", "details" : { "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : 1.0 }, "step 1 of 6" : 22, "step 2 of 6" : 11, "step 3 of 6" : 4, "step 4 of 6" : 0, "step 5 of 6" : 2042, "step 6 of 6" : 373, "note" : "success" } }
View Code

details欄位中的每一步表示的都是時間,"step N of 6"資訊以毫秒為單位顯示步驟耗時的長短。

當from分片收到mongos發來的moveChunks命令時,它會做如下操作:

(1).檢查命令引數;

(2)向配置伺服器申請獲得一個分佈鎖,以便進入遷移過程;

(3)嘗試連線到to分片;

(4)複製資料

(5)與to分片和配置伺服器一起確認遷移是否成功完成。

當to分片收到from分片發來的命令時,它會執行如下操作:

(1)遷移索引;

(2)刪除塊範圍內已經存在的任何資料;

(3)將塊中的所有文件複製到to分片;

(4)在to分片上運行復制期間對這些文件所執行過的操作;

(5)等待to分片將遷移過來的資料複製到副本集的大多數伺服器上。

(6)標誌遷移是否執行成功。

chunks

儲存集合分片所有塊資訊

collections

記錄所有分片集合資訊,該記錄中的記錄不會因為分片集合被刪除而被清除。

databases

記錄叢集中資料庫的資訊,不管資料庫有沒有分片。如資料庫開啟了分片,那麼"partitioned" :欄位的值為true。"primary"記錄資料庫所屬的主分片。所有新集合預設建立在資料庫主分片上。比如當前的集合在某個分片上面還沒有資料那麼不會在該分片上建立集合。所以如果某個分片存在分片的集合,那麼必須將集合的資料移走或者將集合刪除,否則該分片無法刪除。

lockpings

記錄分片執行是否正常的ping記錄資訊

locks

記錄儲存分散式鎖操作資訊。

migrations

mongos

記錄mongos的相關資訊,記錄每一個mongos例項的資訊。

settings

包含平衡器和塊的設定資訊等。

shards

群集分片資訊

tags

記錄分片標籤資訊

transactions

version

群集版本資訊

注意:如果需要修改配置資訊,需要通過連線到mongos切換到config資料庫操作而不是直接連線到配置伺服器中操作。

3.檢視網路連線

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

4.限制連線數量

--maxConns 

mongos可以接受的最大併發連線數。如果此設定高於作業系統配置的最大連線跟蹤閾值,則此設定無效。

注意:在版本2.6中MongoDB刪除了maxIncomingConnections 設定的上限。

三、分片管理

1.新增分片

use admin

db.auth("dba","dba")

sh.addShard("rs-a/192.168.137.10:27010,192.168.137.10:27011,192.168.137.10:27012");

sh.addShard("rs-b/192.168.137.20:28010,192.168.137.20:28011,192.168.137.20:28012");

sh.addShard("rs-c/192.168.137.30:26010,192.168.137.30:26011,192.168.137.30:26012");

sh.status();

2.刪除分片

先當前分片對應資料庫挪到其它的分片上。這裡的"products"指的是資料庫名

db.runCommand( { movePrimary: "products", to: "rs-b" })

然後再刪除分片

db.runCommand({"removeShard":"rs-c"});

 

注意:需要多次執行db.runCommand({"removeShard":"rs-c"});命令來刪除分片,首先平衡器會將分片上的資料進行遷移,可以通過sh.isBalancerRunning()命令查詢是否遷移完成,遷移完成之後再次執行刪除分片命令徹底移除分片。

3.平衡器管理

3.1開啟平衡器

use admin
sh.startBalancer()
或者
sh.setBalancerState(true)

3.2關閉平衡器

use admin
sh.stopBalancer()
或者
sh.setBalancerState(false);

檢視是否關閉,返回flase標識平衡器已關閉,還需要查詢均衡器正在執行情況

sh.getBalancerState();

while( sh.isBalancerRunning() ) {

          print("waiting...");

          sleep(1000);

}

在執行資料庫管理操作之前應該關閉平衡器,關閉平衡器之後,系統不會再進入平衡過程, 但是均衡器的關閉不是立即就完成,所以還需要查詢均衡器是否正在執行.

3.3檢視平衡器開啟狀態

db.settings.find({"_id":"balancer"})
或者
sh.getBalancerState()

3.4檢視平衡器是否在執行

sh.isBalancerRunning()

返回ture代表正在執行,false代表當前沒有在執行。

3.5指定平衡時間

必須先保證平衡器是開啟狀態

use config
sh.setBalancerState( true )

db.settings.update({"_id":"balancer"},
{"$set":{"activeWindows":{"start":"13:00","stop":"16:00"}}},
{upsert:true}
)
  • For HH values, use hour values ranging from 00 - 23.
  • For MM value, use minute values ranging from 00 - 59.

3.6關閉平衡時間

use config

db.settings.update({ _id : "balancer" }, { $unset : { activeWindows : true } })

3.7關閉開啟指定文件的平衡器

關閉

sh.disableBalancing("test.aa")

開啟

sh.enableBalancing("test.aa")

查詢是否關閉文件的平衡器,返回true代表關閉。沒有結果返回沒有關閉,返回報錯代表文件不存在或者文件沒有開啟分片

db.getSiblingDB("config").collections.findOne({_id : "test.aa"}).noBalance;

3.8.備份時注意事項

在執行備份前需要關閉平衡器,但是均衡器的關閉不是立即就完成,所以還需要查詢均衡器是否正在執行,不要在平衡器處於活動狀態時備份,可以備份操作前執行以下查詢:

sh.getBalancerState()

sh.isBalancerRunning()

注意:保證平衡器處於關閉狀態同時sh.isBalancerRunning()返回的不是ture ;也可以通過設定平衡器的平衡時間來維護備份。

4.塊管理

1.修改資料塊大小

單位MB,預設塊大小為64MB。塊越大遷移至分片的耗時就越長。

use config;
查詢當前塊大小
db.settings.find({"_id":"chunksize"})
修改塊大小
db.settings.save( { _id:"chunksize", value: 64 } );

2.手動移動資料塊

2.1查詢文件塊資訊

db.getCollection('chunks').find({"ns":"test.xxxx"})

2.2將塊"$minKey"移動到分片rs-c

移動塊只需要指定塊的返回內的隨便一個值即可,注意塊的範圍不包含上限。

sh.moveChunk("test.xxxx",{"username":"$minKey"},"rs-c")

2.3拆分塊

如果塊的大小超過setting設定的最大塊大小時,系統會禁止移動塊,這時候需要將塊進行拆分。這裡需要指定新的塊範圍,指定下限即可。

sh.splitAt("test.xxxx",{ "username" :"p" })

2.4查詢塊的大小

db.runCommand({ dataSize: "test.xxxx", keyPattern: { "username": 1 }, min: { "username" : "b" }, max: { "username" : "c" } })

單位位元組,需要指定塊的範圍。

2.5無法拆分的特大塊處理

假設使用year/month/day欄位作為分片,某一天業務遭受攻擊導致這天的資料量暴增,但是由於分片的值已經的最小單位了無法再拆分了,這個時候通過塊拆分已經無法解決問題,可以手動將塊移動到非熱點的分片上。

5.重新整理配置資訊

mongos有時無法從配置伺服器正確更新配置資訊,可以使用flushRouterConfig命令手動重新整理快取,如果重新整理還無法解決需要重啟mongos程序。

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

6.刪除分片資料庫

use news

db.dropDatabase()

備註:

本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明連結,否則保留追究責任的權利。

《歡迎交流討論》