MongoShake最佳實踐

咱們在去年開源了MongoShake,能夠用於MongoDB的數據同步,知足用戶多種需求,總體介紹文檔參考這裏。今天,我來主要介紹一下MongoShake的最佳實踐,主要涵蓋如下幾部分:linux

  1. 從MongoDB副本集同步到MongoDB副本集
  2. 從MongoDB副本集同步到MongoDB集羣版
  3. 從MongoDB集羣版同步到MongoDB集羣版
  4. 從MongoDB副本集同步到kafka通道
  5. 雲上MongoDB副本集的雙向同步
  6. 配置文件參數解釋
  7. 其餘問題Q&A說明。這部分我主要列了目前用戶存在的主流問題,這些問題在github上的wiki上都已經有說明,不過是英文的:https://github.com/alibaba/MongoShake/wiki/FAQ

MongoShake的下載路徑咱們提供在了github上,點擊能夠下載不一樣版本的mongoshake:mongo-shake-x.y.z.tar.gz。目前MongoShake提供了配置文件啓動的方式,啓動的命令行:./collector.linux -conf=collector.conf,不一樣的平臺請選擇不一樣的二進制文件,如windows下是collector.windows。git

0. 配置文件

全部的參數都列在了配置文件裏面,目前配置文件較多,用戶可能比較困惑,正常狀況下用戶默認就行,修改的參數只有少部分。
MongoShake支持MongoDB副本集和集羣版的互相同步,還能夠同步到kafka模式,下面列出了幾種常見的同步模式。github

1. 從MongoDB副本集同步到MongoDB副本集

假設源端是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的端也是三副本:10.5.5.5:5005, 10.6.6.6:6006, 10.7.7.7:7007。同步模式是全量+增量同步。
則用戶須要修改如下幾個參數:golang

mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端鏈接串信息,逗號分隔不一樣的mongod
sync_mode = all # all 表示全量+增量,document表示僅全量,oplog表示僅增量
tunnel.address = mongodb://username:password@10.5.5.5:5005, 10.6.6.6:6006, 10.7.7.7:7007 #目的端鏈接串信息,逗號分隔不一樣的mongod

2. 從MongoDB副本集同步到MongoDB集羣版

假設源一樣是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的端是sharding,有多個mongos:20.1.1.1:2021, 20.2.2.2:2022, 20.3.3.3:3033。mongodb

mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端鏈接串信息,逗號分隔不一樣的mongod
sync_mode = all # all 表示全量+增量,document表示僅全量,oplog表示僅增量
tunnel.address = mongodb://username:password@20.1.1.1:2021;20.2.2.2:2022;20.3.3.3:3033 #目的端鏈接串信息,分號分割不一樣的mongos。也能夠只配置部分,配置多個mongos能夠作負載均衡寫入。

3. 從MongoDB集羣版同步到MongoDB集羣版

假設源是2節點:節點1是10.1.1.1:1001, 10.1.1.2:2002, 10.1.1.3:3003;節點2是10.2.2.1:1001, 10.2.2.2:2002, 10.2.2.3:3003。目的端是sharding,有多個mongos:20.1.1.1:2021, 20.2.2.2:2022, 20.3.3.3:3033。數據庫

mongo_urls = mongodb://username1:password1@10.1.1.1:1001,10.1.1.2:2002,10.1.1.3:3003;mongodb://username2:password2@10.2.2.1:1001,10.2.2.2:2002,10.2.2.3:3003 #源端鏈接串信息,逗號分隔同一個shard不一樣的mongod,分號分隔不一樣的shard。
sync_mode = all # all 表示全量+增量,document表示僅全量,oplog表示僅增量
tunnel.address = mongodb://username:password@20.1.1.1:2021;20.2.2.2:2022;20.3.3.3:3033 #目的端鏈接串信息,分號分割不一樣的mongos。也能夠只配置部分,配置多個mongos能夠作負載均衡寫入。
context.storage.url = mongodb://username1:password1@10.5.5.5:5555,10.5.5.6:5556 # 若是源端是sharding,此處須要配置源端sharding的cs的地址

4. 從MongoDB副本集同步到kafka通道

假設源一樣是三副本:10.1.1.1:1001, 10.2.2.2:2002, 10.3.3.3:3003,目的kafka是50.1.1.1:6379,topic是test。windows

mongo_urls = mongodb://username:password@10.1.1.1:1001,10.2.2.2:2002,10.3.3.3:3003 #源端鏈接串信息,逗號分隔不一樣的mongod
sync_mode = oplog # 若是目的端不是mongodb,僅支持增量同步模式
tunnel.type = kafka
tunnel.address = test@50.1.1.1:6379

5. 雲上MongoDB副本集的雙向同步

雲上副本集的雙向同步能夠參考副本集的單向同步,可是須要注意的有如下幾點,假設A和B之間雙向同步:api

  1. 須要搭建2個mongoshake,一個從A到B,另外一個從B到A
  2. 兩條mongoshake不能同時用全量+增量(all)模式,正常應該是一個庫爲空(假設B),另外一個有數據。那麼從A到B先發起一次全量+增量同步,等待全量同步完畢之後,再從B到A發起一次增量同步。
  3. 雙向同步須要依賴gid的開啓,這個能夠聯繫燭昭(經過售後聯繫),開啓gid將會重啓實例形成秒級別閃斷。
  4. gid用於記錄數據的產生地,好比從A產生的數據導入到B之後,不會被再導入回A,這樣就不會產生環形複製。須要注意的是,這個gid只能用於增量,這也是第2條爲何一個方向通道是全量+增量,另外一個方向通道須要搭建增量的緣由。
  5. 雲下開源的mongodb不能使用雙向同步,由於gid的修改是在內核裏面,因此開源不支持。
  6. sharding一樣也支持雙向同步

6. 部分配置文件參數解釋

具體請查看配置文件的註釋,此處只作簡單解釋restful

  • mongo_urls: 源mongodb的鏈接地址
  • mongo_connect_mode: 源端鏈接的模式,有幾種模式可選:從seconary拉取;從primary拉取;secondary優先拉取;單節點拉取
  • sync_mode: sync模式,有幾種模式可選:全量,增量,全量+增量
  • http_profile: 提供restful接口,用戶能夠查看一些內部運行狀況,也能夠對接監控。
  • system_profile: profile端口,能夠查看進程運行的堆棧狀況。
  • log: log日誌相關參數。
  • filter.namespace.black: 黑名單過濾。黑名單內的庫表不會被同步,剩下的同步。
  • filter.namespace.white: 白名單過濾。白名單內的庫表會被同步,剩下的過濾掉。黑白名單最多隻能配置一個,不配置會同步全部庫表。
  • filter.pass.special.db: 有些特別的庫表會被過濾,如admin,local, config庫,若是必定要開啓,能夠在這裏進行配置。
  • oplog.gids: 用於雲上雙向同步。
  • shard_key: 內部對數據多線程的哈希方式,默認collection表示按表級別進行哈希。
  • worker: 增量階段併發寫入的線程數,若是增量階段性能不夠,能夠提升這個配置。
  • worker內部相關配置: worker.batch_queue_size, adaptive.batching_max_size, fetcher.buffer_capacity, 關於內部隊列的相關配置,具體請參考github wiki文檔。
  • worker.oplog_compressor: 壓縮模式,若是是非direct模式開啓這個能夠減小網絡傳輸的開銷。
  • tunnel.address: 目的端對接的地址。
  • context.storage: checkpoint存儲的位置,database表示把數據存入MongoDB,api表示把數據存入用戶本身提供的http接口。
  • context.storage.url: checkpoint寫入到哪一個MongoDB,若是源是sharding,此處配置cs地址,checkpoint會寫入admin庫;若是是副本集,不配置,會默認寫入源庫,配置則寫入配置的庫裏面。
  • context.address: checkpoint寫入的表的名字。
  • context.start_position: checkpoint啓動開始拉取的增量時間位點。若是自己checkpoint已經存在(參考上述context的位置),那麼則按照context信息進行拉取,若是不存在,則按照這個位點進行增量拉取。
  • master_quorum: 若是以主備模式拉取同一個源,則這個參數須要啓用。
  • transform.namespace: 命名空間的轉換,a.b:c.d表示把源端a庫下面的c表同步到目的端c庫下面的d表。
  • replayer.dml_only: 默認不一樣步DDL,false表示同步DDL。DDL包括建表,刪庫,建索引等語句。
  • replayer.executor.upsert: 目的端若是update語句對應的主鍵id不存在,是否將update語句更改成insert語句。
  • replayer.executor.insert_on_dup_update: 目的端若是insert語句對應的主鍵id已經存在,是否將insert語句更改成update語句。
  • replayer.conflict_write_to: 對於寫入衝突的狀況,是否須要記錄衝突的文檔。
  • replayer.durable: 測試選項,false表示取消寫入,只用於拉取調試。
  • replayer.collection_parallel: 全量同步按表併發的併發度。
  • replayer.document_parallel: 全量同步同一個表內併發寫入的線程數。
  • replayer.document_batch_size: 全量同步一次性batch的大小。
  • replayer.collection_drop: 若是目的庫表存在,是否先刪除目的庫再進行同步。

7. Q&A說明

此處記載幾個常見的問題:網絡

Q. mongoshake是否會同步config, local, admin庫

A: 不會同步。若是用戶必定要把admin的庫同步到別的,那麼能夠經過命名轉換功能(配置transform.namespace)把admin庫同步到別的數據庫,同時配置filter.pass.special.db參數:

  1. filter.pass.special.db = admin
  2. transform.namespace = admin.abc:target.abc # 把admin庫下面的abc同步到target庫的abc

Q. 從MongoDB同步到MongoDB發現全量階段目的端MongoDB壓力過大怎麼辦?

A: 用戶能夠下降全量同步配置replayer的相關參數,以下降目的端壓力。

Q. 從MongoDB同步到MongoDB發現全量階段同步時間太久,怎麼辦?

A: 用戶能夠定位一下看看目的慢的緣由是什麼,正常狀況下能夠提升全量配置replayer的相關參數,以提升全量同步的性能。但也有可能,問題的瓶頸是源端/網絡端/通道cpu,內存等壓力太高,都是有可能的。

Q. 到底什麼是checkpoint?

A: checkpoint是記錄增量同步的位點狀況,mongoshake的啓動就是根據這個位點來進行的,好比咱們已經同步到10點鐘了,那麼這個時候掛掉了,若是沒有位點,那麼只能從頭開始拉,位點的意義就是在於斷點續傳。在mongoshake中,位點信息是以64位時間戳來標記的(ts字段,準確的說是32位時間戳+計數),若是發生掛掉重啓,那麼會從源庫的oplog表中尋找這個位點,並今後開始日後進行同步。
到這裏,用戶可能會問,那麼mongoshake裏面位點是存儲在哪裏的?存儲的位置就是取決於用戶context的相關配置,以副本集爲例,checkpoint是存儲於源庫的mongoshake庫的ckpt_default表,其大概內容長這個樣子:

rszz-4.0-2:PRIMARY> use mongoshake
switched to db mongoshake
rszz-4.0-2:PRIMARY> show collections
ckpt_default
rszz-4.0-2:PRIMARY> db.ckpt_default.find()
{ "_id" : ObjectId("3d75e8b872d91278c3be0cc9"), "name" : "rszz-4.0-2", "ckpt" : Timestamp(1566556865, 196096) }

其中ckpt對應的field就是checkpoint。
用戶可能還會問,那麼mongoshake的checkpoint是怎麼存儲的,何時會存儲?答案是,checkpoint是按期存儲的,若是有數據同步,那麼checkpoint的更新會很頻繁(秒級別);若是沒有數據同步,好比這個時候用戶源端就是沒有寫入,那麼默認是分鐘級別更新一次心跳checkpoint。假設mongoshake數據位點記錄是10:00:00,可是數據已經同步到10:00:10,這個時候mongoshake掛掉了,下次會從10:00:00從新開始同步,因爲DML自己具備冪等性,數據的重複回放是OK的。那麼用戶可能會問,DDL怎麼辦?參考下面問題。

Q. 如何同步DDL?DDL能保證冪等性嗎?

A: 設置replayer.dml_only = false能夠同步DDL。DDL不能保證冪等性。在mongoshake裏面,若是發現是DDL語句,會卡一個全局的barrier,讓當前DDL語句同步,而後再卡一個全局barrier,等當前DDL語句同步完成,再接着併發同步接下來的oplog,barrier的卡鎖伴隨着checkpoint的強制刷新。可是因爲DDL同步和checkpoint的刷新並非一個院子操做,若是用戶剛好在同步DDL完成和checkpoint刷新之間,進程掛掉了,那麼沒有辦法,重啓之後確定會持續報錯,用戶須要手動運維解決,好比跳過這個DDL,或者目的端近些一個反向操做(原來DDL是建庫,須要進行刪除庫;原來是建索引,須要進行刪索引操做)。可是,這個機率很低。

Q. mongoshake碰到同步出錯的狀況,會跳過這個錯誤,繼續同步嗎?

A: 不會,會持續報錯,用戶須要關注日誌的運行狀況。

Q. 除了日誌如何知道目前mongoshake的同步狀況?

A: mongoshake有提供restful接口,能夠監控mongoshake的內部同步狀況,參考wiki: How to monitor the MongoShake,正常狀況下lsn_ckpt.time會一直增加,若是這個數值不增加了,那麼就表示同步出現問題了。

Q. 全量同步是否會同步索引?

A: 會同步索引,顯示全量同步,全量同步完畢後會同步索引,接着是增量同步。

Q. 選擇all模式同步,若是掛掉之後重啓,是否會從新發起一次全量同步?進入增量階段,是否要修改成oplog增量模式,而後再重啓?

A: 顯示全量同步,全量同步完畢會寫入checkpoint,而後進行增量同步,增量同步階段會不斷更新checkpoint。對於mongoshake來講,是否進行全量同步取決於checkpoint,若是checkpoint存在且合法,那麼只會進入增量同步;不然,會先進行全量同步,而後是增量。那麼checkpoint怎麼知道是存在的,就是context裏面的參數的位置決定;那麼怎麼知道checkpoint是合法的?若是最老的oplog的時間位點小於checkpoint,那麼就是合法的,證實增量能接上。

Q. 個人數據量很大,幾百G/幾個T/幾十個T,all模式同步有什麼要注意的地方?

A: 最須要注意的就是,全量同步完畢,增量可否接上。mongoshake是根據oplog的位點來決定全量結束是否要進行增量,若是全量花了2天,可是oplog表只能存儲1天,那麼全量同步完畢之後mongoshake就會報錯退出,這是由於增量的位點丟失了。因此若是全量很大,同步時間勢必好久,那麼就須要放大oplog的表的大小以維持增量oplog。
其餘還須要注意的就是壓力問題,如何選取適當的參數應對對於源端/目的端的壓力,減小對業務的影響。用戶也能夠決定從一個hidden結點,護着一個獨立的secondary結點進行拉取。

Q. 同步出現xxx錯誤,怎麼辦?

A: 這個我在github的wiki基本都有總結,能夠先看下github的faq。若是裏面沒有提到的,能夠提交issue進行反饋。

Q. 目前mongoshake有校驗工具嗎?

A: 目前script下面有個comparison.py的全量校驗腳本校驗數據的一致性。那麼如何進行增量的校驗呢?目前尚未,敬請期待。

Q. sharding模式同步有啥須要注意的嗎?

A: 若是源端是sharding,那麼目前須要關閉balancer,在v2.1非穩定版本里面,咱們支持了不關閉balancer,用戶能夠進行試用,可是目前這個是非穩定版本。此外源端若是是sharding,DDL的同步(replayer.dml_only = false)不能開啓。

Q. 我把數據寫入到kafka,怎麼從kafka中拉取數據,發現直接拉取出現亂碼

A: 請先看下wiki: https://github.com/alibaba/MongoShake/wiki/FAQ#q-how-to-connect-to-different-tunnel-except-direct
kafka通道中的數據是有控制信息在裏面的,用戶很差直接剝離,能夠用receiver進行對接。目前receiver對接後全部oplog都打印到控制檯,用戶也能夠本身修改receiver代碼,對接下游服務。固然,這個須要用戶懂golang語言,這可能有一些學習成本在裏面。後面咱們會看看如何以更好的形式對接給用戶。

Q. 我發現mongoshake創建之後對源端性能有所影響,出現了一些慢查詢。

A: 目前全量階段因爲是掃表等操做,會對源端產生一些影響。增量階段,正常狀況影響很小,由於目前oplog找對應ts是二分模式。

Q. 是否能夠把一個MongoDB同步到多個MongoDB?

A: 能夠,須要啓動多個mongoshake。對於不一樣的mongoshake,能夠修改寫入不一樣地方的checkpoint便可(好比表名修改一下),或者直接修改不一樣的collector.id。此外,須要注意的是,同一個目錄下啓動多個mongoshake,若是collector.id相同,是沒法啓動成功的。參考:https://github.com/alibaba/MongoShake/wiki/FAQ#q-how-to-sync-data-from-one-mongodb-to-several-target-mongodb

 

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索