mongo备份测试(cp vs mongodump)

mongo 备份测试

环境

db

3 router
3 config
3 shard (3 repl / shard)

oplog: 10G
cache: 1G
maxconn: 8000

replSet name node name type ip port role
dbpd_dafs_config dbpd_dafs_config0 config 10.255.2.67 8600 master
dbpd_dafs_config dbpd_dafs_config1 config 10.255.2.69 8600 slave
dbpd_dafs_config dbpd_dafs_config2 config 10.255.2.70 8600 slave
—————— ——————– ——– ————- ——- ——–
single single0 router 10.255.2.67 20600 none
single single1 router 10.255.2.69 20600 none
single single2 router 10.255.2.70 20600 none
—————— ——————– ——– ————- ——- ——–
dbpd_dafs_shard0 dbpd_dafs_shard0d0 shard 10.255.2.67 9600 master
dbpd_dafs_shard0 dbpd_dafs_shard0d1 shard 10.255.2.69 9600 slave
dbpd_dafs_shard0 dbpd_dafs_shard0d2 shard 10.255.2.70 9600 slave
—————— ——————– ——– ————- ——- ——–
dbpd_dafs_shard1 dbpd_dafs_shard1d0 shard 10.255.2.67 9601 master
dbpd_dafs_shard1 dbpd_dafs_shard1d1 shard 10.255.2.69 9601 slave
dbpd_dafs_shard1 dbpd_dafs_shard1d2 shard 10.255.2.70 9601 slave

硬盘性能

这里备份和数据盘是在同一个,拷贝时的性能如下
iostat -x 1 10
avg-cpu: %user %nice %system %iowait %steal %idle
0.34 0.00 0.73 2.39 0.00 96.55

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 532.00 3195.00 104532.00 816160.00 494.07 109.54 29.21 80.97 20.59 0.27 99.90

备份是在压测完后

性能监测

mongostat –port 20600 -u mgmon -p wbdba –authenticationDatabase admin
mongostat: (1 mongos)
insert query update delete getmore command flushes mapped vsize res faults qrw arw net_in net_out conn time
*0 *0 8834 *0 0 8880|0 0 0B 3.74G 446M 0 0|0 0|0 12.9m 2.25m 3160 Sep 16 13:00:44.214
*0 *0 13234 *0 0 12656|0 0 0B 3.74G 446M 0 0|0 0|0 18.4m 3.36m 3160 Sep 16 13:00:45.213
*0 *0 20691 *0 0 19966|0 0 0B 3.74G 446M 0 0|0 0|0 29.0m 5.23m 3160 Sep 16 13:00:46.217
*0 *0 16649 *0 0 17994|0 0 0B 3.74G 446M 0 0|0 0|0 26.1m 4.22m 3160 Sep 16 13:00:47.213
*0 *0 9610 *0 0 9619|0 0 0B 3.74G 446M 0 0|0 0|0 14.0m 2.44m 3160 Sep 16 13:00:48.214
[OVERALL], RunTime(ms), 744887
[OVERALL], Throughput(ops/sec), 26849.7100902553
2000w

测试

说明

数据集:
1 record = 10 fields * 100 char
2000w ~= 22G(data) ~= 34(storage)

每个集合采用分片,3 shard平均分布
sh.enableSharding(“webank”)
sh.shardCollection(“webank.lizer_2000w”,{_id:1})
sh.shardCollection(“webank.lizer_2000w_b”,{_id:1})
sh.shardCollection(“webank.lizer_2000w_c”,{_id:1})
sh.shardCollection(“webank.lizer_2000w_d”,{_id:1})
sh.shardCollection(“webank.lizer_8000w”,{_id:1})
sh.shardCollection(“webank.lizer_16000w”,{_id:1})
数据导入ycsb,平均2w~5w ops(upsert)
./bin/ycsb load mongodb -threads 4000 -P workloads/2000w 1>logs/2000w.log 2>logs/2000w.err &
./bin/ycsb load mongodb -threads 4000 -P workloads/2000w_b 1>logs/2000w_b.log 2>logs/2000w_b.err &
./bin/ycsb load mongodb -threads 1000 -P workloads/2000w_c 1>logs/2000w_c.log 2>logs/2000w_c.err &
./bin/ycsb load mongodb -threads 80 -P workloads/2000w_d 1>logs/2000w_d.log 2>logs/2000w_d.err &
./bin/ycsb load mongodb -threads 80 -P workloads/8000w 1>logs/8000w.log 2>logs/8000w.err &
./bin/ycsb load mongodb -threads 80 -P workloads/16000w 1>logs/16000w.log 2>logs16000w.err &

备份时,是在数据压力下(有大量的ops时,经常备份失败,跟oplog cache大小和ops大小有关)
primary shard2
mongodump 导出采用了gzip,备份集会小些,消耗会有提升
job=4同时mongodump备份使用了cron每分钟检查,所以一般都是3个分片同时备份,io会有些影响

每个分片耗时空间比较(cp和mongodump –oplog –gzip)

job=4
| storage/G | data/G | max_c/G | num_c | cp min | cp size | dump min(zip) | dump size(zip) | dump min | dump size |
|———–|——–|———|——-|——–|———|—————|—————-|———-|———–|
| 22 | 14 | 7 | 2 | | | 6 | 11 | | |
| 33 | 21 | 7 | 3 | | | 6 | 16 | | |
| 44 | 28 | 7 | 4 | | | 8 | 24 | | |
| 91 | 57 | 29 | 5 | 4 | 100 | 25,22 | 45,42 | 4.4 | 59 |
| 156 | 114 | 57 | 6 | 9 | 150 | 110 | 82 | 24 | 115 |

job=6
| shard | storage/G | data/G | max_c/G | num_c | cp min | cp size | dump min(zip) | dump size(zip) | dump min | dump size |
|——–|———–|——–|———|——-|——–|———|—————|—————-|———-|———–|
| shard1 | 114 | 129 | 56.64 | 6 | 4.96 | 145G | 53.50 | 82G | 22.88 | 115G |
| shard2 | 194 | 113 | 62.04 | 6 | 7.33 | 164G | 61.26 | 81G | 24.21 | 114G |
| shard3 | 141 | 120 | 55.33 | 6 | 6.33 | 148G | 63.85 | 86G | 26.85 | 121G |
|——–|———–|——–|———|——-|——–|———|—————|—————-|———-|———–|
| shard1 | 64 | 58 | 28.73 | 5 | 1.68 | 61G | 26.85 | 42G | 4.05 | 59G |
| shard2 | 132 | 57 | 29 | 5 | 2.93 | 101G | 32.98 | 41G | 11.80 | 58G |
| shard3 | 74 | 58 | 29.26 | 5 | 1.98 | 79G | 27.25 | 42G | 6.43 | 59G |
|——–|———–|——–|———|——-|——–|———|—————|—————-|———-|———–|
| shard1 | 34 | 29 | 8.3 | 4 | 0.83 | 31G | 7.73 | 21G | 3.01 | 30G |
| shard2 | 50 | 28 | 5.77 | 4 | 1.93 | 70G | 8.66 | 21G | 3.08 | 29G |
| shard3 | 43 | 29 | 7.67 | 4 | 1.30 | 48G | 7.08 | 21G | 2.63 | 30G |
|——–|———–|——–|———|——-|——–|———|—————|—————-|———-|———–|
| shard1 | 25 | 20 | 6.81 | 3 | 0.36 | 23G | 6.61 | 15G | 2.13 | 21G |
| shard2 | 44 | 22 | 7.35 | 3 | 1.76 | 64G | 7.18 | 17G | 2.63 | 23G |
| shard3 | 24 | 21 | 7.58 | 3 | 0.90 | 40G | 6.53 | 16G | 2.33 | 22G |

分析

  • mongodump

    • mongodump 采用的是collections级别的多线程并发,备份速度跟最大集合的大小有很大关系

    • 默认备份是4job
      2019-09-17T18:47:24.862+0800 [……………………] webank.lizer_2000w 243014/6599570 (3.7%)
      2019-09-17T18:47:24.862+0800 [……………………] webank.lizer_8000w 500216/26422088 (1.9%)
      2019-09-17T18:47:24.862+0800 [###…………………] webank.lizer_2000w_b 886019/6421483 (13.8%)
      2019-09-17T18:47:24.862+0800 [……………………] webank.lizer_2000w_d 200147/7633598 (2.6%)
      2019-09-17T18:47:24.862+0800

    • 全备时指定–oplog,当备份oplog时间过长,备份开始被记录oplog 点被刷出,备份oplog失败
      2019-09-16 13:41:10 - [ERROR] - [ dbpd_dafs_shard1 : 9601 ] fullbackup fail, will try next time…
      2019-09-16T13:41:10.339+0800 Failed: oplog overflow: mongodump was unable to capture all new oplog entries during execution

    • mongodump会拖慢oplog的回放速度,当ops很大时(测试时4w ops),oplog不够大,从库变为recovery模式(需要重新全量从其他库同步)
      2019-09-17T11:25:35.147+0800 Failed: error writing data for collection webank.lizer_2000w to disk: error reading collection: EOF

    • 分片为了负载均衡,balancer会movechunk,版本会变化,导致报错
      2019-09-16 14:00:50 - [ERROR] - [ dbpd_dafs_shard1 : 9601 ] fullbackup fail, will try next time…
      2019-09-16T14:00:50.436+0800 Failed: error dumping oplog: error writing data for collection .oplog to disk: cannot dump with oplog if admin.system.version is modified

db.system.version.find()
{ “_id” : “featureCompatibilityVersion”, “version” : “3.6” }
{ “_id” : “authSchema”, “currentVersion” : 5 }
{ “_id” : “shardIdentity”, “clusterId” : ObjectId(“5d2c1fb40d084aac6626a93e”), “shardName” : “dbpd_dafs_shard1”, “configsvrConnectionString” : “dbpd_dafs_config/10.255.2.67:8906,10.255.2.69:8906,10.255.2.70:8906” }
{ “_id” : “minOpTimeRecovery”, “configsvrConnectionString” : “dbpd_dafs_config/10.255.2.67:8906,10.255.2.69:8906,10.255.2.70:8906”, “minOpTime” : { “ts” : Timestamp(1568612543, 14678), “t” : NumberLong(11) }, “minOpTimeUpdaters” : 0, “shardName” : “dbpd_dafs_shard1” }
{ “_id” : “startRangeDeletion”, “ns” : “webank.lizer_2000w_b”, “epoch” : ObjectId(“5d7f1575b43a1fb988beedd8”), “min” : { “_id” : “user5779780441414634474” }, “max” : { “_id” : “user5793529265481788866” } }

  • 恢复,应用备份->rebuild index->应用oplog,恢复时间更长
  • 空间小
  • cp
    • 需要fsyncLock,
    • 速度快
    • 恢复快,无需重建索引
    • 占用空间较大
    • 恢复后需要修改配置文件(ip,port,分片关系,副本集)

备份脚本

当前脚本

  • 每分钟循环检测当前状态是否需要备份(前提是slave,跳过master、recovery)
  • 每次备份检测时,都检查当前的分片备份目录是否存在pid文件,存在说明已有进程在备份,跳过后续步骤
  • 当没有全备||周六且无其他当天的备份||fullback.lock 触发全备(mongodump)
  • 增备条件为oplog使用量大于0.5,已经备份oplog windows占总windows比例小于0.8
  • 当增备时,最近的增备或全备的最后的oplog record被oplog cap刷出,则touch fullback.lock,下次检测时触发全备

问题

  • mongodump全备速率慢
  • 增备策略需要优化,当突增大量的文档更新操作时,oplog容易被刷出,导致增备失败
  • 对于分片,开启了collection shard,balancer和手动movechunk 会产生大量的oplog,其次版本变化导致全备失败
  • mongodump会拖慢oplog的回放速度,测试时,两个从库,mongodump的更容易变成recovery模式(需要手动重新全量同步)
  • 控制节点增备策略问题,增备oplog增长比较慢,很难触发增备

改进

  • 全备改用cp选项,(fsynclock)
  • 防止硬盘的IO过高,增加可同时进行全备的个数
  • 增备策略
  • 优化控制节点的备份

其他

  • oplog

    • 数据collection的drop,在oplog中记录为一条cmd,不会产生大量的oplog
    • 数据的movechunk记录的时一条条d/i,oplog可能会被刷出
      dbpd_dafs_shard0:SECONDARY> db.oplog.rs.find({“ns”:{$ne:””}}).sort({$natural:-1}).limit(10)
      { “ts” : Timestamp(1568758966, 3314), “t” : NumberLong(10), “h” : NumberLong(“4434686517193231122”), “v” : 2, “op” : “c”, “ns” : “config.$cmd”, “ui” : UUID(“0e25def1-a270-4136-9e5d-87ce4a04219c”), “wall” : ISODate(“2019-09-17T22:22:46.411Z”), “o” : { “drop” : “cache.chunks.webank.lizer_16000w” } }
      { “ts” : Timestamp(1568758966, 3313), “t” : NumberLong(10), “h” : NumberLong(“4547986359210973331”), “v” : 2, “op” : “d”, “ns” : “config.cache.collections”, “ui” : UUID(“c51c0ca2-c708-413d-892d-df930745bf30”), “wall” : ISODate(“2019-09-17T22:22:46.411Z”), “o” : { “_id” : “webank.lizer_16000w” } }
      { “ts” : Timestamp(1568758964, 4), “t” : NumberLong(10), “h” : NumberLong(“-2093926210899775967”), “v” : 2, “op” : “c”, “ns” : “webank.$cmd”, “ui” : UUID(“d5b23f5d-68eb-4bb8-9e63-979c1e8e3ba4”), “wall” : ISODate(“2019-09-17T22:22:44.432Z”), “o” : { “drop” : “lizer_16000w” } }
      { “ts” : Timestamp(1568729753, 6255), “t” : NumberLong(10), “h” : NumberLong(“-2146114616361287121”), “v” : 2, “op” : “d”, “ns” : “webank.lizer_16000w”, “ui” : UUID(“d5b23f5d-68eb-4bb8-9e63-979c1e8e3ba4”), “fromMigrate” : true, “wall” : ISODate(“2019-09-17T14:15:53.420Z”), “o” : { “_id” : “user213834907078841758” } }
  • oplog相关进程
    ReplBatcher
    rsSync-0
    WT OplogTruncaterThread: local.oplog.rs
    monitoring keys for HMAC

等我熬尽一日苦,喂你一口甜
-------------本文结束感谢您的阅读-------------