文章目录
MongoDB复制集同步
一、同步
- 同步发生的范围是在复制集集群中的Prmary和secondary之间
- 同步涉及到的日志是oPlog,
1.1 同步类型
- 节点之间数据同步方式有两种:Init sync(初始同步)和keep(同步保持)
1.1.1 Init sync
- 这种类型发生在一下场景:
1.secondary第一次加入,就会进行初始化同步,把所有的数据同步过来
2.Secondary被移出,重新加入后由于数据落后,也会进行initsync应用新的日志。如果节点落后的数量超过opolog大小,也
就是说,oplog被覆盖过,那么他会启用一次全量备份,把所有数据复制过来。所以,已经有大量的数据时,加入一个新节点
要注意全量复制带来的网络负担。应用高峰期时,不适合做这些操作。
如果只是很短暂的移除就没事
-
Init sync类型的同步可以理解为从节点已经跟不上主节点,Oplog已经无能为力,因此从节点不得不全量同步,该操作一般会重新初始化备份节点,开销较大
-
前面描述的是自动Init sync,也可以手动进行。停止对应节点然后删除目录中的文件,找一个比较新的节点,然后把较新节点目录中的文件拷贝到要sync的节点目录中
1.1.2 keep(持续复制)
- 如果从节点比主节点落后很少,那么通过oplog同步即可,一般oplog大战推荐磁盘的5%
- MongoDB会避免从隐藏节点或者延迟节点,或者vote为0的节点同步数据。
- 同步过程是多线程的
1.4 查看Oplog
- 查看oplog中数据
shard1:PRIMARY> use local
switched to db local
shard1:PRIMARY>
shard1:PRIMARY> db.oplog.rs.find().limit(1).toArray()
[
{
"ts" : Timestamp(1565483849, 2294),
"t" : NumberLong(6),
"h" : NumberLong("631336405990407044"),
"v" : 2,
"op" : "d",
"ns" : "ifaas_data.car",
"ui" : UUID("5bab001c-6c0b-4631-a3d3-eb2b2e6b9190"),
"wall" : ISODate("2019-08-11T00:37:29.980Z"),
"o" : {
"time" : ISODate("2019-07-08T00:07:43Z"),
"tid" : "292258481368717",
"_id" : ObjectId("5d4131e52597696cbe4c4ff1")
}
}
]
shard1:PRIMARY>
1.5 查看secondary状态
- 查看secondary的同步状态,是否有延迟
db.printSlaveReplicationInfo()
shard3:PRIMARY> db.printSlaveReplicationInfo()
source: 192.168.13.51:30002
syncedTo: Wed Aug 21 2019 04:28:19 GMT-0400 (EDT)
0 secs (0 hrs) behind the primary
- 这里给出了是从什么时候同步的,落后了多少等关键信息
二、原理
参考自:MongoDB运维实战
2.1 副本集原理
- 副本集是一组提供冗余和高可用性的mongd进程。
2.2 状态
- 副本集有很多状态,比如Primary、Secondary、ARBITER、STARTUP、DOWN、REMOVED、ROLLBACK等。
2.3 同步
- Secondary初次同步数据,会进行init sync从Primary或者其他Secondary同步全量数据
- 同步过程
1.Secondary从Priamry同步全量数据,(注意不包含local库下的数据,local库下包含oplog,选举日志,启动日志等信息)。同步是基于三个命令实现
的:listDatabases、listCollections和cloneCollection。
2.同步过程中的数据,Secondary通过复制oplog来重放数据,保证数据一致,这里有可能oplog中的一些数据已经在第一步同步完毕了,不过oplog是幂
等性的,重复应用没有影响。
3.Secondary开始构建索引,索引的信息已经在第一步同步完成。
2.4 成员数量
- 采用奇数个成员是因为奇数和偶数的容错性是一样的,必须保证存活过半的节点,比如5和6都只能允许2个节点宕机,因此奇数个节点性价比更好。
- 3.0以后版本,副本集的成员数量最多可以达到50,但是拥有投票权的节点最多是7个。
- 优先级:副本集成员可以配置优先级,如果优先级为0则不能选举为Primary,Arbiter的Priority就是0。选举过程如果低优先级的Secondary成为Primary,那么会继续选举将优先级高的Secondary选举为Primary。
将Priority配置为0可以做冷备份。
2.5 Hidden和Delayed
- Hidden节点对客户端不可见,不能被选举为主,可以做一些数据备份,离线计算。
- Delayed节点必须是Hidden节点,并且数据落后于Primary(落后时间可配置),当写入错误数据到Primary时可以利用Delayed节点来做数据的恢复。
2.6 RollBack
-
如果Primary写入数据尚未同步给其他节点就宕机,那么就会选举出新的Primary,旧的Primary起来之后,需要回滚以便保持数据和新的Primary一致。旧的Primary会将回滚的数据写到rollback路径下,管理员也使用mongorestore进行恢复
-
mongodb会避免从隐藏节点或者延迟节点,或者vote为0的节点同步数据。
2.7 选举
- 当副本集启动之后或者Primary不可用之后,会触发副本集的选举
- 选举期间,没有Primary,因此副本集可读但是不可写
- 如果过半节点不可用,Primary将降级为Secondary,此时集群不可读不也可写,处于不可用状态。但是有个特例,如果客户端的read concern配置的不是Primary,那么Secondary可以提供只读功能
- 影响选举的因素包括:心跳时间(默认10S)、节点优先级(优先级为0不能成为Primary)并且算法会尽量保证优先级高的节点被选举为Primary、投票(vote)
1.vote是0的节点,其Priority必须为0 (即不能投票就不能成为主)
2.Priority大于0的成员,vote必须为1 (能够被选举,必须要有投票权)
投票权还和状态有关。处于Primart、Secondary、Arbiter、RECOVERING、ROOLBACK这些状态的节点才有投票权
三、小结
- 主节点将操作内容写入到Oplog这个数据库,从节点从这个数据库同步到从节点的Oplog数据库,并且也可以作为源同步给其他节点。
- 默认Oplog集合大小为磁盘的5%,如果从节点落后太多,无法跟上主节点,就会触发Init sync全量同步
- db.getReplicationInfo()用于查看oplog的状态、大小、存储的时间范围。如下说明Oplog里面保存了近期80小时的数据,配置的2GB的大小
- rs.printReplicationInfo() :查看 oplog 的状态,输出信息包括 oplog 日志大小,操作日志记录的起始时间。这两个命令其实差不多,显示方式不一样
shard1:PRIMARY> db.getReplicationInfo()
{
"logSizeMB" : 2048,
"usedMB" : 2031.51,
"timeDiff" : 287465,
"timeDiffHours" : 79.85,
"tFirst" : "Sat Aug 10 2019 20:37:29 GMT-0400 (EDT)",
"tLast" : "Wed Aug 14 2019 04:28:34 GMT-0400 (EDT)",
"now" : "Wed Aug 14 2019 04:28:41 GMT-0400 (EDT)"
}
shard1:PRIMARY>
shard1:PRIMARY>
shard1:PRIMARY> db.printReplicationInfo()
configured oplog size: 2048MB
log length start to end: 287465secs (79.85hrs)
oplog first event time: Sat Aug 10 2019 20:37:29 GMT-0400 (EDT)
oplog last event time: Wed Aug 14 2019 04:28:34 GMT-0400 (EDT)
now: Wed Aug 14 2019 04:28:43 GMT-0400 (EDT)
shard1:PRIMARY>
- Primary运行rs.stepDown()可以让Primary下线,有时候主从切换的时候有用。
四、参考
- [1] mongodb 复制集 维护小结
- [2] MongoDB oplog详解