一、MongoShake
1.1MongoShake簡介
MongoShake是一個以go語言編寫的通用的平台型服務,通過讀取MongoDB叢集的Oplog日志,對MongoDB的資料進行複制,後續通過記錄檔實作特定需求。
MongoShake從源庫抓取oplog資料,然後發送到各個不同的tunnel通道。源庫支援:ReplicaSet,Sharding,Mongod,目的庫支援:Mongos,Mongod。現有tunnel通道類型有:
- Direct:直接寫入目的MongoDB
- RPC:通過net/rpc方式連接配接
- TCP:通過tcp方式連接配接
- File:通過檔案方式對接
- Kafka:通過Kafka方式對接
- Mock:用于測試,不寫入tunnel,抛棄所有資料
消費者可以通過對接tunnel通道擷取關注的資料,例如對接Direct通道直接寫入目的MongoDB,或者對接RPC進行同步資料傳輸等。此外,使用者還可以自己建立自己的API進行靈活接入。下面2張圖給出了基本的架構和資料流。
MongoShake對接的源資料庫支援單個mongod,replica set和sharding三種模式。目的資料庫支援mongod和mongos。如果源端資料庫為replica set,建議使用備庫以減少主庫的壓力;如果為sharding模式,那麼每個shard都将對接到MongoShake并進行并行抓取。對于目的庫來說,可以對接多個mongos,不同的資料将會哈希後寫入不同的mongos。
1.2 應用場景
- 從MongoDB副本集同步到MongoDB副本集
- 從MongoDB副本集同步到MongoDB叢集版
- 從MongoDB叢集版同步到MongoDB叢集版
- 從MongoDB副本集同步到kafka通道
- 雲上MongoDB副本集的雙向同步(自建不支援,雲MongoDB核心有調整:在oplog中加入uk字段,辨別涉及到的唯一索引資訊)
1.3 基本特性
- 并行複制
MongoShake提供了并行複制的能力,複制的粒度選項(shard_key)可以為:id,collection或者auto,不同的文檔或表可能進入不同的哈希隊列并發執行。id表示按文檔進行哈希;collection表示按表哈希;auto表示自動配置,如果有表存在唯一鍵,則退化為collection,否則等價于id。
按表哈希可以保證一個表内的操作的順序一緻性,但不能保證不同表之間的順序一緻性;按文檔哈希可以保證一個表内對同一個文檔(主鍵_id)的操作的順序一緻性,但不能保證對不同文檔操作的順序一緻性。
-
HA方案
MongoShake定期将同步上下文進行存儲,存儲對象可以為第三方API或者源庫。目前的上下文内容為“已經成功同步的oplog時間戳”。在這種情況下,當服務切換或者重新開機後,通過對接該API或者資料庫,新服務能夠繼續提供服務。
此外,MongoShake還提供了Hypervisor機制用于在服務挂掉的時候,将服務重新拉起。
- 過濾
提供黑名單和白名單機制選擇性同步db和collection。
- 壓縮
支援oplog在發送前進行壓縮,目前支援的壓縮格式有gzip, zlib, 或deflate。
- Checkpoint
Checkpoint是用于辨別同步的位點資訊,比如checkpoint="2018-01-01 12:34"辨別已經同步到了"2018-01-01 12:34"這個位點了,那麼這個時候如果MongoShake異常退出,那麼下次重新開機可以繼續從"2018-01-01 12:34"開始拉取,而不是從頭開始。下面介紹具體實作原理:
MongShake采用了ACK機制確定oplog成功回放,如果失敗将會引發重傳,傳輸重傳的過程類似于TCP的滑動視窗機制。這主要是為了保證應用層可靠性而設計的,比如解壓縮失敗等等。為了更好的進行說明,先來定義幾個名詞:
LSN(Log Sequence Number),表示已經傳輸的最新的oplog序号。
LSN_ACK(Acked Log Sequence Number),表示已經收到ack确認的最大LSN,即寫入tunnel成功的LSN。
LSN_CKPT(Checkpoint Log Sequence Number),表示已經做了checkpoint的LSN,即已經持久化的LSN。
LSN、LSN_ACK和LSN_CKPT的值均來自于Oplog的時間戳ts字段,其中隐含限制是:LSN_CKPT<=LSN_ACK<=LSN。
如上圖所示,LSN=16表示已經傳輸了16條oplog,如果沒有重傳的話,下次将傳輸LSN=17;LSN_ACK=13表示前13條都已經收到确認,如果需要重傳,最早将從LSN=14開始;LSN_CKPT=8表示已經持久化checkpoint=8。持久化的意義在于,如果此時MongoShake挂掉重新開機後,源資料庫的oplog将從LSN_CKPT位置開始讀取而不是從頭LSN=1開始讀。因為oplog DML的幂等性,同一資料多次傳輸不會産生問題。但對于DDL,重傳可能會導緻錯誤。
- 索引、DDL同步優化 & 4.0事務支援
從v1.5版本開始,MongoShake優化了DDL語句,保證了正确性。其基本原理是通過添加全局barrier,一旦發現oplog為DDL語句或者索引,那麼會等待這條oplog成功寫入目的端并更新checkpoint後,才會放開後續的同步。對于DML語句的同步,還是延用之前的并發模式。在以下非常極端的情況下,可能會存在報錯,需要運維介入解決:目的端已經寫入DDL但是checkpoint還沒更新,這個時候MongoShake挂了,那麼重新開機之後這條DDL重傳寫入将會導緻報錯。
同樣從v1.5版本,MongoShake對事務語句進行了支援。
- 全量同步
從v1.5版本開始,MongoShake支援全量同步,有3種模式可選:全量同步+增量同步,隻全量同步,隻增量同步。為了保證高效性,内部同樣采用并發處理。
- 排障和限速
MongoShake對外提供Restful API,提供實時檢視程序内部各隊列資料的同步情況,便于問題排查。另外,還提供限速功能,友善使用者進行實時控制,減輕資料庫壓力。
二、方案
2.1 多活方案
在開源MongoDB下,可以根據控制流量分發來達到多活的需求。比如下面這個圖,需要通過proxy進行流量分發,比如對a, b庫的寫操作分發到左邊的MongoDB,對c庫的寫操作分發到右邊的MongoDB,源庫到目的庫的MongoShake鍊路隻同步a, b庫(MongoShake提供按db、collection的過濾功能),目的庫到源庫的MongoShake鍊路隻同步c庫。這樣就解決了環形複制的問題。
2.2 容災方案
MongoShake搭建了異地容災鍊路。使用者在2個機房分别部署了2套應用,正常情況下,使用者流量通過DNS/SLB隻通路主應用,然後再通路到主MongoDB,資料通過MongoShake在2個機房的資料庫之間進行同步,一旦機房1不可用,DNS/SLB将使用者流量切換到備上,然後繼續對外提供讀寫服務。
三、驗證
3.1 環境介紹
本實驗采用兩套單節點副本集作為源端和一套單節點副本集做為目的端進行測試,使用的MongoShake版本為2.4.1。(多節點在配置上隻需添加對應節點配置即可)
- MongoShake1:single1 test1>single3
- MongoShake1:single1 test2>single2
- MongoShake1back:single3 test1>single1
- MongoShake2back:single3 test2>single2
名稱 | 版本 | 端口 |
---|---|---|
single1 | 4.2.3 | 27017 |
single2 | 27018 | |
single3 | 27019 | |
MongoShake1 | 2.4.1 | 9101、9102、9103 |
MongoShake2 | 9201、9202、9203 | |
MongoShake1back | 9301、9302、9303 | |
MongoShake2back | 9401、9402、9403 |
3.2 功能驗證
3.2.1 多活驗證
#single1配置檔案
conf.version = 2
id = mongoshake1
master_quorum = false
full_sync.http_port = 9101
incr_sync.http_port = 9102
system_profile_port = 9103
log.level = info
log.dir =/usr/local/mongo-shake/single1
log.file = collector.log
log.flush = false
sync_mode = all
mongo_urls = mongodb://root:[email protected]:27017
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27019
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test1
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckptone
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#single3配置檔案
conf.version = 2
id = mongoshake1back
master_quorum = false
full_sync.http_port = 9301
incr_sync.http_port = 9302
system_profile_port = 9303
log.level = info
log.dir =/usr/local/mongo-shake/single1back
log.file = collector.log
log.flush = false
sync_mode = all
mongo_urls = mongodb://root:[email protected]:27019
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27017
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test2
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckptoneback
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#開啟雙向同步任務
[root@zijie mongo-shake]# ./start.sh mongoshake1.conf
[root@zijie mongo-shake]# ./start.sh mongoshake1back.conf
#single1
single1:PRIMARY> use test1
switched to db test1
single1:PRIMARY> db.t1.insert({"id":1})
WriteResult({ "nInserted" : 1 })
single1:PRIMARY> db.t1.insert({"id":2})
WriteResult({ "nInserted" : 1 })
single1:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.001GB
mongoshake 0.000GB
test1 0.000GB
test2 0.000GB
single1:PRIMARY> use test2
switched to db test2
single1:PRIMARY> db.t2.find()
{ "_id" : ObjectId("5e9dbe6e115d93488122f909"), "id" : 1 }
{ "_id" : ObjectId("5e9dbe70115d93488122f90a"), "id" : 2 }
#single3
single3:PRIMARY> use test1
switched to db test1
single3:PRIMARY> db.t1.find()
{ "_id" : ObjectId("5e9dbe203d06ebef5e549110"), "id" : 1 }
{ "_id" : ObjectId("5e9dbe243d06ebef5e549111"), "id" : 2 }
single3:PRIMARY> use test2
switched to db test2
single3:PRIMARY> db.t2.insert({"id":1})
WriteResult({ "nInserted" : 1 })
single3:PRIMARY> db.t2.insert({"id":2})
WriteResult({ "nInserted" : 1 })
3.2.2 容災驗證
#single1配置檔案
conf.version = 2
id = mongoshake1
master_quorum = false
full_sync.http_port = 9101
incr_sync.http_port = 9102
system_profile_port = 9103
log.level = info
log.dir =/usr/local/mongo-shake/single1
log.file = collector.log
log.flush = false
sync_mode = all
mongo_urls = mongodb://root:[email protected]:27017
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27019
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test1
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckptone
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#single2配置檔案
conf.version = 2
id = mongoshake2
master_quorum = false
full_sync.http_port = 9201
incr_sync.http_port = 9202
system_profile_port = 9203
log.level = info
log.dir =/usr/local/mongo-shake/single2
log.file = collector.log
log.flush = false
sync_mode = all
mongo_urls = mongodb://root:[email protected]:27018
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27019
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test2
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckpttwo
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#single1back配置檔案
conf.version = 2
id = mongoshake1back
master_quorum = false
full_sync.http_port = 9301
incr_sync.http_port = 9302
system_profile_port = 9303
log.level = info
log.dir =/usr/local/mongo-shake/single1back
log.file = collector.log
log.flush = false
sync_mode = incr
mongo_urls = mongodb://root:[email protected]:27019
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27017
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test1
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckptoneback
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#single2back配置檔案
conf.version = 2
id = mongoshake2back
master_quorum = false
full_sync.http_port = 9401
incr_sync.http_port = 9402
system_profile_port = 9403
log.level = info
log.dir =/usr/local/mongo-shake/single2back
log.file = collector.log
log.flush = false
sync_mode = incr
mongo_urls = mongodb://root:[email protected]:27019
mongo_cs_url =
mongo_s_url =
tunnel = direct
tunnel.address = mongodb://root:[email protected]:27018
tunnel.message = raw
mongo_connect_mode = secondaryPreferred
filter.namespace.black =
filter.namespace.white =test2
filter.pass.special.db =
filter.ddl_enable = true
checkpoint.storage.url =
checkpoint.storage.db = mongoshake
checkpoint.storage.collection = ckpttwoback
checkpoint.start_position = 1970-01-01T00:00:00Z
transform.namespace =
full_sync.reader.collection_parallel = 6
full_sync.reader.write_document_parallel = 8
full_sync.reader.document_batch_size = 128
full_sync.collection_exist_no_drop = false
full_sync.create_index = background
full_sync.executor.insert_on_dup_update = true
full_sync.executor.filter.orphan_document = false
full_sync.executor.majority_enable = false
incr_sync.mongo_fetch_method = oplog
incr_sync.oplog.gids =
incr_sync.shard_key = auto
incr_sync.worker = 8
incr_sync.worker.oplog_compressor = none
incr_sync.worker.batch_queue_size = 64
incr_sync.adaptive.batching_max_size = 1024
incr_sync.fetcher.buffer_capacity = 256
incr_sync.executor.upsert = false
incr_sync.executor.insert_on_dup_update = true
incr_sync.conflict_write_to = none
incr_sync.executor.majority_enable = false
#開啟single1、single2到single3
#single1
single1:PRIMARY> use test1
switched to db test1
single1:PRIMARY> db.t1.insert({"id":1})
WriteResult({ "nInserted" : 1 })
single1:PRIMARY> db.t1.insert({"id":2})
WriteResult({ "nInserted" : 1 })
#single2
single2:PRIMARY> use test2
switched to db test2
single2:PRIMARY> db.t2.insert({"id":1})
WriteResult({ "nInserted" : 1 })
single2:PRIMARY> db.t2.insert({"id":2})
WriteResult({ "nInserted" : 1 })
#single3
single3:PRIMARY> use test1
switched to db test1
single3:PRIMARY> db.t1.find()
{ "_id" : ObjectId("5e9dc3fd3d06ebef5e549112"), "id" : 1 }
{ "_id" : ObjectId("5e9dc3ff3d06ebef5e549113"), "id" : 2 }
single3:PRIMARY> use test2
switched to db test2
single3:PRIMARY> db.t2.find()
{ "_id" : ObjectId("5e9dc43b77d631fe2074e4c3"), "id" : 1 }
{ "_id" : ObjectId("5e9dc43d77d631fe2074e4c4"), "id" : 2 }
#應用停寫,停止同步任務,将應用切到目的端
#開啟反向同步任務
[root@zijie mongo-shake]# ./start.sh mongoshake1back.conf
[root@zijie mongo-shake]# ./start.sh mongoshake2back.conf
#single3插入反向同步資料
single3:PRIMARY> use mongoshake
switched to db mongoshake
single3:PRIMARY> show tables;
ckptoneback
ckpttwoback
system.profile
single3:PRIMARY> use test1
switched to db test1
single3:PRIMARY> db.t1.insert({"id":3})
WriteResult({ "nInserted" : 1 })
single3:PRIMARY> db.t1.insert({"id":4})
WriteResult({ "nInserted" : 1 })
single3:PRIMARY> use test2
switched to db test2
single3:PRIMARY> db.t2.insert({"id":3})
WriteResult({ "nInserted" : 1 })
single3:PRIMARY> db.t2.insert({"id":4})
WriteResult({ "nInserted" : 1 })
#single1
single1:PRIMARY> db.t1.find()
{ "_id" : ObjectId("5e9dc3ff3d06ebef5e549113"), "id" : 2 }
{ "_id" : ObjectId("5e9dc3fd3d06ebef5e549112"), "id" : 1 }
{ "_id" : ObjectId("5e9dc6df115d93488122f90b"), "id" : 3 }
{ "_id" : ObjectId("5e9dc6e1115d93488122f90c"), "id" : 4 }
#single2
single2:PRIMARY> db.t2.find()
{ "_id" : ObjectId("5e9dc43d77d631fe2074e4c4"), "id" : 2 }
{ "_id" : ObjectId("5e9dc43b77d631fe2074e4c3"), "id" : 1 }
{ "_id" : ObjectId("5e9dc6e8115d93488122f90d"), "id" : 3 }
{ "_id" : ObjectId("5e9dc6ea115d93488122f90e"), "id" : 4 }
四、問題總結
-
權限
對于完全同步,MongoShake需要每個資料庫的讀取權限。對于增量,MongoShake需要
資料庫的讀取權限和資料庫的寫入權限local
。mongoshake
-
版本支援
MongoShake不支援3.0以下的MongoDB版本。
-
MongoShake重新開機
是sync.mode
,重新開機後如果檢查點存在且有效,這意味着最早的記錄檔小于檢查點,則MongoShake将僅運作增加同步。否則,MongoShake将再次運作完全同步,此後,将運作增加同步。是以,如果使用者仍想運作完全同步但檢查點存在,all
則應手動删除檢查點。mongoshake.ckpt_default
-
MongoShake支援同步DDL
使用
選項。但是DDL不是幂等操作,一旦失敗,oplog可能會重放,是以啟用DDL在最新版本中可能會出現問題。replayer.dml_only
-
斷點恢複
MongoShake支援基于檢查點機制的斷點恢複,每次啟動時,它都會讀取檢查點,這是一個時間戳,訓示已準備好重播多少資料。之後,它将從此時間戳開始從源中提取資料。是以重新開機時不會丢失資料。
- oplog一緻性
mongoshake不支援oplog的嚴格一緻性,當
shard_key
auto/collection
,mongoshake支援順序一緻性其中同一命名空間(裝置
ns
),該序列可以得到保證。如果
shard_key
為
id
,則mongoshake支援最終一緻性。
-
監控
MongoShake提供了api(在配置中預設為9100
)來監控伺服器方面的内部狀态:http_profile
worker
:顯示内部工作者狀态,包括
worker_id
,
jobs_in_queue
jobs_unack_buffer
last_unack
last_ack
count
sentinel
:顯示前哨配置:(
OplogDump
轉儲oplog日志,“ 0”表示無日志,“ 1”表示采樣,“ 2”表示全部轉儲),
DuplicatedDump
(如果啟用則将重複的oplog寫入日志),
Pause
(如果出現以下情況,整個mongoshake同步将被暫停啟用),
TPS
(控制資料同步的速度)。
repl
:顯示總體狀态:(
logs_get
我們獲得多少記錄檔),
logs_repl
(我們重播多少記錄檔),
logs_success
(我們成功重播多少記錄檔),
lsn
(最後發送),
lsn_ack
(除0以外的所有工作隊列中的最小ack值),
lsn_ckpt
(檢查點)
now
replset
tag
who
conf
:顯示配置。
可以使用
curl
指令通路此端口。此外,提供了
mongoshake-stat
腳本,通過以下實時方式通過靜态API監控MongoShake。
./mongoshake-stat --port=9100
結果将每秒清除一次
logs_get
:一秒鐘内我們獲得了多少個oplog。
logs_repl
:我們在一秒鐘内重播了多少oplog。
logs_success
:我們在一秒鐘内成功重播了多少記錄檔,即TPS。
- 雙活
使用者可以使用filter(
filter.namespace.white
和
filter.namespace.black
)來實作此功能。目前,過濾器的粒度為集合。
例如,我在一個名為mongodb的副本集中有三個資料庫
a
b
而
c
。假設源plicateSet為
source-mongo
,目标副本集為
target-mongo
,是以我們建構了兩個MongoShakes 分别從
source-mongo
和擷取記錄檔
target-mongo
。在第一個MongoShake中,我們僅過濾資料庫名稱等于
a
或
b
在第二個MongoShake中我們僅過濾資料庫名稱
c
使用者可以使用自己的
proxy
程式,資料分發,這樣的寫作
a
,并
b
會去到源資料庫,同時
c
轉到目标。
- 資料校驗
腳本進行驗證,以從源資料庫和目标資料庫中擷取并比較資料。但是請注意,它僅比較大綱資訊,例如資料庫編号,收集編号,文檔編号,兩邊都存在相同的“ _id”。是以,如果comparision.py
源資料庫中有一個條目{"_id":1, "a":1}
,而目标資料庫中有另一個條目,則此比較代碼無法驗證。{"_id":1, "a":2}
-
系統庫同步
出于某些特殊原因,将資料寫入“ admin”資料庫,但是“ admin”資料庫無法同步,如何将源MongoDB上“ admin”下的集合同步到目标MongoDB上的另一個集,
以便“管理者”資料庫也可以同步,但是使用者應非常小心。這是我們的建議,假設使用者要将“ admin.source”同步到“ users.target”:filter.pass.special.db
- 設定
為讓“管理者”資料庫通過。filter.pass.special.db = admin
-
為在其他名稱空間被過濾時讓“ admin.source”通過。對于目前的v2.0.7版本,“使用者”也應添加到白名單中。filter.namespace.white = admin.source
-
為将源中的“ admin.source”傳遞到目标上的“ users.target”。transform.namespace = admin.source:users.target
參考文檔:
https://yq.aliyun.com/articles/603329、
https://yq.aliyun.com/articles/719704