Mongodb movePrimary(轉載)

轉載自:Mongodb movePrimary_大數據_運維開發網_運維開發技術經驗分享 (qedev.com)

move Primary

首先根據上一篇來短暫的回憶一下平衡器。Mongodb會開啓一個線程balance專門負責數據的平衡工作,查看系統中所有的shard,發現不平衡的情況就選擇將其中shard服務器的chunk遷移到其它服務器,讓整個系統達到平衡

平衡策略

  • shard的數據大小超過了shard配置的數據大小,從中選擇chunk遷移到別處
  • 找到shard中有違法tag規則的chunk,將這些chunk遷移到符合 tag規範的shard中
  • 找出tag中各個shard中chunk數,如果chunk數的差值大於閾值,從較多的shard移動chunk到較少的shard中

平衡器工作內容

  • 保持不同分片之間的數據平衡
  • 儘量最小化不同分片之間交互的數據塊次數

主分片

在mongodb的分片集羣中,創建的第一個分片會被默認爲主分片,如果片鍵選擇不合理,會導致集羣不均衡,解決方法想到的有:

  • 使用moveChunk將數據移動到某個分片
  • 換片鍵,當然必須是沒有創建的集合
  • 如果置換片鍵之後依舊失敗。比如寫入量太大,或者一下子import太多的數據。分享一個粗暴的方式,換主分片,因爲數據都會大量的寫入主分片,再開始移動。

在採用移動主分片之前,,我懷疑或許是我的片鍵設置的有問題,但是其實在數據量較小的情況下,一切運作良好,好吧,我開始利用其它的片鍵:

1.使用_id的哈希片鍵,且不論索引會佔多大的空間,結果是數據依舊無法平衡

2.使用time,儘管升序片鍵不被推薦,但是可以採用半人工干預:開始使用了addShardTag,然後addTagRange,給平衡器指定特定時間範圍數據位於某個shard上面,不過似乎沒有起作用,其實分析一下,在原來可以均衡的片鍵下都沒有成功,就平衡策略的第二種情形也是無法平衡的。

所以開始利用movePrimary力求數據全部寫到這個主分片中,以降低原來主分片中磁盤的壓力。其使用方法:

db.runCommand({"movePrimary":"test","to":"shard_1"})

上述命令將主分片移動到shard_1中。在移動的過程中或許會耗費非常多的時間,原因在於:

  1. 如果原來的主分片中存在大量的未分片的集合,在movePrimary中會將這部分集合全部移動過來,並創建索引。簡直驚人!
  2. 創建索引的方式採用的是前臺創建形式。所謂前臺創建索引,所有的集合都將被鎖住,包括讀寫,直到所有的索引都被創建完畢,是整個db的鎖,所以,在移動的過程中不能有任何其他的讀寫操作。索引創建過程默認是前臺方式,我們順便了解下後臺創建方式。後臺創建過程不會影響其他的操作,但是其代價是速度很慢。特別的如果索引的大小大於可用的RAM,那麼創建的過程將會非常漫長。
  3. 如果在移動的過程中沒有禁止其他的操作,你進入一個未分片的集合,那麼movePrimary也不會阻止對它的 讀寫,但是這個過程誰都無法保證最後的結果,行爲未知。所以,在movePrimary之前,進行了一些操作:

  4. 檢查所有的集合是否已經創建索引

  5. 檢查集合是否已經分片,就此還寫了個腳本
var getStats=function(name){
 var col_stats=db.getCollection(name).stats(); 
 if(col_stats.sharded) 
 { 
   db.shard_status.insert({"name":name,"shard":true}) 
 } 
 else 
 {
   db.shard_status.insert({"name":name,"shard":false}) 
  } 
}
  var nameArr=db.getCollectionNames(); 
  var i=0; 
  for(;i<nameArr.length;i++){
  getStats(nameArr[i]); 
 }
  1. 查看未分片的集合,對於一些小集合,我還是給予了分片, 避免db被鎖住太長時間,查看CurrentOp,如果有createIndex等操作,請等待
  2. 刪除shard_status,開始執行movePrimary命令,等待返回
  3. 在每個mongos使用
db.runCommand("flushRouterConfig")

*如果在使用movePrimary命令移動未分片集合,必須重新啓動所有的mongos,或者使用flushRouterConfig,這個命令必須執行在對數據庫的讀寫之前。它的本質告訴mongos這些集合位於新的分片中,更新mongos中元數據的配置。其實對於我們的操作,已經讓所有的集合使用了分片,這個過程可以不做。

出現的問題

  1. movePrimary之後,目標分片無法顯示對應的集合,發現在當前的主分片中這些集合的索引還沒有創建,因爲沒有創建索引完畢,就開始向裏面寫入數據
  2. 報錯 
  3. { "ok" : 0, "errmsg" : "clone failed" }

     

    進入到分片中的mongod,發現分片中出現相同的名字,這個過程發生在我試圖切換回原來的主分片。官方也對此給出了結論,指出如果原來的主分片中存在相同的集合名稱將會發生錯誤

  4. 性能影響

    如果原來的集合已經不平衡,切換主分片,集合依舊不平衡,數據分在某個分片中,將會影響查詢的效率

    如果從一臺較好的服務器切換到一個配置交差的服務器,其IO與平衡器的運行將會是一個問題,IO的增加,寫入會降低,查詢超時。只有那種主分片快滿了,沒有其他的當時下,短暫緩解主分片數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章