利用MongoDB的SplitVector命令實現併發資料遷移
背景
資料遷移是資料庫運維中一個很常見的場景。資料遷移分為全量和增量。為了追求速度,通常我們會採用併發的方式對資料進行全量遷移。在全量匯出資料時,通常都會選擇做到記錄級的併發,因此通常會涉及到對需要匯出的某個表(集合)按照併發度進行切分(分割槽)的過程。現有常用做法是通過若干個skip加limit來找到一些分割槽點,然後就可以併發同時匯出多個分割槽。事實上MongoDB還有一個SplitVector命令特別適合用來做集合的分割槽。本文將介紹一下如何利用這個命令來對集合做分割槽,實現併發資料遷移。
命令簡介
SplitVector命令原是在sharding中chunk分裂時需要用的一個內部命令,是mongos在準備分裂某個chunk前發給這個chunk所在shard以計算分裂點(SplitPoint)時使用的。但是這個命令也可以用於普通的副本集,我們可以把副本集中的集合看作一個唯一的chunk,利用這個命令來為這個chunk計算分裂點,從而達到為某個集合進行分割槽的目的。
SplitVector命令的使用在官方文件中沒有介紹,只說明瞭其實一個內部命令,但是使用命令的Help卻可以看到:
db.runCommand({splitVector:"test.test", help:1})
{
"help" : "help for: splitVector Internal command.
examples:
{ splitVector : "blog.post" , keyPattern:{x:1} , min:{x:10} , max:{x:20}, maxChunkSize:200 }
maxChunkSize unit in MBs
May optionally specify `maxSplitPoints` and `maxChunkObjects` to avoid traversing the whole chunk
{ splitVector : "blog.post" , keyPattern:{x:1} , min:{x:10} , max:{x:20}, force: true }
`force` will produce one split point even if data is small; defaults to false
NOTE: This command may take a while to run",
"lockType" : 0,
"ok" : 1
}
從幫助文件中可以大致看到,這個命令大致是這麼使用的:
db.runCommand({splitVector:"blog.post", keyPattern:{x:1}, min{x:10}, max:{x:20}, maxChunkSize:200})
接下來介紹一下各個引數及其含義。
欄位 | 型別 | 描述 |
---|---|---|
splitVector | string | splitVector的操作物件集合名 |
keyPattern | document | chunk分裂使用的分割槽鍵,必須擁有索引,在sharding中就是shard key,在副本集中通常就指定成主鍵_id索引 |
min | document | 可選引數,分割槽資料集的最小值,如果沒有指定,那麼使用MinKey |
max | document | 可選引數,分割槽資料集的最大值,如果沒有指定,那麼使用MaxKey |
maxChunkSize | integer | 可選引數,和『force』引數二者必須指定一個。分割槽後每個chunk的最大大小 |
maxSplitPoints | integer | 可選引數,分裂點個數上限 |
maxChunkObjects | integer | 可選引數,分割槽後每個chunk最大包含的記錄數,預設為250000 |
force | boolean | 可選引數,和『maxChunkSize』引數二者必須指定一個。預設情況下如果當前chunk的資料大小小於maxChunkSize則不會進行分裂。如果指定了『force』為true,那麼會強制在當前chunk的中位點進行分裂,返回一個分裂點。預設為false。 |
這麼多引數到底怎麼用呢?我怎麼知道出來的結果是怎樣的?沒有更詳細的文件,只有啃原始碼了。
原理
SplitVector的原理是遍歷指定的『keyPattern』索引,根據指定的『maxChunkSize』找到滿足以下條件的n個分裂點:分裂後的每個新的chunk的大小約為『maxChunkSize』的一半。如果集合當前大小比『maxChunkSize』小或者集合記錄數為空,那麼返回一個空的分裂點集合。如果指定了『force: true』,那麼會忽略傳入的『maxChunkSize』引數,並強制在集合的中位點進行分片,這時候只會產生一個分裂點。
在尋找分裂點時首先會根據集合的平均文件大小計算一個分裂後每個chunk所包含的文件數:
keyCount = maxChunkSize / (2 * avgObjSize)
如果指定了『maxChunkObjects』引數,並且『maxChunkObjects』比keyCount小,會使用『maxChunkObjects』作為keyCount。接下來就是遍歷索引,每遍歷keyCount個key,就得到一個分裂點(第keyCount+1個key),直到達到『maxSplitPoints』(若有指定)或遍歷結束。因此最終得到的分裂點個數:
splitPointCount = keyTotalCount / (keyCount + 1)
其中keyTotalCount為索引的key總數。
使用案例
知道了原理後,就知道如何去傳引數了,如果要精確控制得到的分裂點個數(以便控制併發數),這裡可以給出一個公式及推導過程。現在我們有以下公式:
1. splitPointCount = partitionCount - 1
2. splitPointCount = keyTotalCount / (keyCount + 1)
3. keyCount = maxChunkSize / (2 * avgObjSize)
由上述公式可以推匯出
maxChunkSize = (keyTotalCount / (partionCount - 1) - 1) * 2 * avgObjSize
由於所有集合都有_id欄位上的唯一索引,並且每個文件都有_id欄位,因此我們可以直接利用集合文件的個數docCount作為索引key的個數。文件個數和avgObjSize都可以通過collStats命令得到。注意引數中的『maxChunkSize』是以MB為單位的,最終傳到命令的時候需要轉換一下,並且在服務端中事實上會將『maxChunkSize』做個向下取整,因此最終計算出來的keyCount可能比我們設想的要小,這樣就會導致最終得到的分裂點個數比我們想要的多。為了達到我們的需求,最好加上『maxSplitPoints』這個可選引數對分裂點進行限制,這樣我們允許最後一個分割槽比其他分割槽包含更多的文件數。
接下來舉個具體的例子,假設現在需要將某個集合分成10個分割槽以支援10個併發同時對外匯出資料,這個集合共有10240條文件,avgObjSize是1024,那麼根據上述公式可以計算得到:
maxChunkSize = (10240 / (10 - 1) - 1) * 2 * 1024 = 2MB
這樣我們執行如下命令:
db.runCommand({splitVector:"test.test", keyPattern:{_id:1}, maxChunkSize:2, maxSplitPoints:9})
這樣就會只得到9個分裂點。
相關文章
- dm資料庫遷移命令資料庫
- 遷移sqlserver資料到MongoDbSQLServerMongoDB
- MongoDB 資料遷移 備份 匯入(自用)MongoDB
- mongodb資料遷移2種方式比較MongoDB
- 【北亞資料恢復】MongoDB資料遷移檔案丟失的MongoDB資料恢復案例資料恢復MongoDB
- 利用offline datafile檔案方式遷移資料
- Azure Storage 利用 azCopy 複製遷移資料
- 利用rman copy的方法實現儲存上裸裝置資料檔案的遷移ITPUB
- mongodb資料庫備份與恢復(資料庫資料遷移)MongoDB資料庫
- 資料遷移新技能,MongoDB輕鬆同步至ClickHouseMongoDB
- MongoDB遷移工具MongoshakeMongoDB
- 快速實現地圖遷移資料視覺化地圖視覺化
- 金倉資料庫資料遷移實戰:從MySQL到KES的順利遷移資料庫MySql
- Mongodb資料遷移步驟MongoDB
- 【Redis 技術探索】「資料遷移實戰」手把手教你如何實現線上 + 離線模式進行遷移 Redis 資料實戰指南(scan模式遷移)Redis模式
- 快速實現本地資料備份與FTP遠端資料遷移FTP
- 記十億級Es資料遷移mongodb成本節省及效能優化實踐MongoDB優化
- Mysql百萬級資料遷移,怎麼遷移?實戰過沒?MySql
- 實戰程式碼(二):Springboot Batch實現定時資料遷移Spring BootBAT
- 伺服器資料遷移的方法-硬體不同如何遷移資料伺服器
- Hadoop資料遷移MaxCompute最佳實踐Hadoop
- ORM實操之資料庫遷移ORM資料庫
- Jenkins搭建與資料遷移實踐Jenkins
- 線上資料遷移,數字化時代的必修課 —— 京東雲資料遷移實踐
- Kafka資料遷移Kafka
- Harbor資料遷移
- gitlab資料遷移Gitlab
- 資料庫遷移資料庫
- 資料遷移方案 + Elasticsearch在綜合搜尋列表實現Elasticsearch
- 利用Redis實現高併發計數器Redis
- 在Ubuntu 14.04上備份,還原和遷移MongoDB資料庫UbuntuMongoDB資料庫
- 【Datapump】Oracle資料泵遷移資料命令參考(expdp/impdp說明)Oracle
- 利用魯棒控制實現深度強化學習駕駛策略的遷移強化學習
- cassandra百億級資料庫遷移實踐資料庫
- 如何實現CDH到雲原生大資料平臺的快速平滑遷移?大資料
- 資料遷移(1)——通過資料泵表結構批量遷移
- 使用SQL SERVER儲存過程實現歷史資料遷移SQLServer儲存過程
- 【Redis 技術探索】「資料遷移實戰」手把手教你如何實現線上 + 離線模式進行遷移Redis資料實戰指南(離線同步資料)Redis模式
- ABP8.1的資料遷移