oplog是 local库下的一个固定集合, Secondary就是通过查看 Primary 的 oplog这个集合来进行复制的。每个节点都有 oplog,记录着从主节点复制过来的信息,这样每个成员都可以作为同步源给其他节点。
Oplog 可以说是 Mongodb Replication的纽带了。
一、副本集数据同步的过程¶
1、Primary节点写入数据 2、Secondary通过读取 Primary的 oplog得到复制信息,开始复制数据并且将复制信息写入到自己的 oplog 3、如果某个操作失败,则备份节点停止从当前数据源复制数据(只有当同步源的数据损坏或者数据与主节点不一致时才可能发生) 4、如果某个备份节点由于某些原因挂掉了,当重新启动后,就会自动从 oplog的最后一个操作开始同步 5、同步完成后,将信息写入自己的 oplog
--由于复制操作是先复制数据,复制完成后再写入 oplog,有可能相同的操作会同步两份,不过 MongoDB在设计之初就考虑到这个问题,将 oplog的同一个操作执行多次,与执行一次的效果是一样的。
二、oplog的作用¶
- 当 Primary进行写操作的时候,会将这些写操作记录写入 Primary的 Oplog 中,而后 Secondary会将 Oplog 复制到本机并应用这些操作,从而实现 Replication的功能。
- 同时由于其记录了 Primary上的写操作,故还能将其用作数据恢复。
- 可以简单的将其视作 Mysql中的 binlog。
三、oplog的增⻓速度¶
- oplog是固定大小,只能保存特定数量的操作日志
- oplog使用空间的增⻓速度跟系统处理写请求的速度相当
四、oplog注意事项¶
local.oplog.rs特殊的集合。用来记录 Primary节点的操作。 为了提高复制的效率,复制集中的所有节点之间会相互的心跳检测(ping)。每个节点都可以从其他节点上获取 oplog。
oplog中的一条操作。不管执行多少次效果是一样的
五、oplog的大小¶
第一次启动复制集中的节点时, MongoDB会建立 Oplog,会有一个默认的大小,这个大小取决于机器的操作系统
shard1:SECONDARY> rs.printReplicationInfo() //oplog的状态
configured oplog size: 30263.68505859375MB
log length start to end: 19952916secs (5542.48hrs)
oplog first event time: Wed Sep 11 2019 10:56:34 GMT+0800 (CST)
oplog last event time: Wed Apr 29 2020 09:25:10 GMT+0800 (CST)
now: Wed Apr 29 2020 09:25:11 GMT+0800 (CST)
shard1:SECONDARY> db.getReplicationInfo() //查看 oplog的状态、大小、存储的时间范围
{
"logSizeMB" : 30263.68505859375,
"usedMB" : 10283.51,
"timeDiff" : 19952977,
"timeDiffHours" : 5542.49,
"tFirst" : "Wed Sep 11 2019 10:56:34 GMT+0800 (CST)",
"tLast" : "Wed Apr 29 2020 09:26:11 GMT+0800 (CST)",
"now" : "Wed Apr 29 2020 09:26:12 GMT+0800 (CST)"
}
5.1 capped collection¶
capped collection是 MongoDB中一种提供高性能插入、读取和删除操作的固定大小集合,当集合被填满的时候,新的插入的文档会覆盖老的文档。
没有指定 oplog大小, MongoDB将创建一个默认大小的 oplog:
- 对于 Unix和 Windows系统
oplog大小依赖于存储引擎:
| 存储引擎 | 默认 oplog大小 | 下限 |
|---|---|---|
| In-Memory存储引擎 | 物理内存的5% | 50MB |
| WiredTiger存储引擎 | 空闲磁盘空间的5% | 990MB |
- 对于 64-bit macOS系统
默认的 oplog大小是 192MB物理内存或空闲磁盘空间,具体取决于存储引擎:
| 存储引擎 | 默认 oplog大小 |
|---|---|
| In-Memory存储引擎 | 192MB物理内存 |
| WiredTiger存储引擎 | 192MB空闲磁盘空间 |
oplogSizeMB --在 mongod创建 oplog前,可使用该参数定义 oplog的大小
replSetResizeOplog --启动副本集后,可使用该命令去改变 oplog的大小,允许动态调整 oplog大小而无需重新启动进程。
repl:PRIMARY> db.getReplicationInfo().logSizeMB
1166.24609375
repl:PRIMARY> db.adminCommand({replSetResizeOplog:1,size:2000})
repl:PRIMARY> db.getReplicationInfo().logSizeMB
2000
5.2 数据同步¶
在副本集中,有两种数据同步方式:
- initial sync(初始化):这个过程发生在当副本集中创建一个新的数据库或其中某个节点刚从宕机中恢复,或者向副本集中添加新的成员的时候,默认的,副本集中的节点会从离它最近的节点复制 oplog来同步数据,这个最近的节点可以是 primary也可以是拥有最新 oplog副本的 secondary节点。该操作一般会重新初始化备份节点,开销较大
- replication(复制):在初始化后这个操作会一直持续的进行着,以保持各个 secondary节点之间的数据同步。
initial sync
当遇到上面例子中无法同步的问题时,只能使用以下两种方式进行 initial sync了
#第一种方式
就是停止该节点,然后删除目录中的文件,重新启动该节点。这样,这个节点就会执行 initial sync
注意:通过这种方式, sync的时间是根据数据量大小的,如果数据量过大, sync时间就会很⻓
同时会有很多网络传输,可能会影响其他节点的工作
#第二种方式
停止该节点,然后删除目录中的文件,找一个比较新的节点,然后把该节点目录中的文件拷⻉到要 sync的节点目录中
通过上面两种方式中的一种,都可以重新恢复 "port=33333"的节点。改变一直处于 RECOVERING状态的错误。
六、oplog数据结构¶
下面来分析一下 oplog中字段的含义,通过下面的命令取出一条 oplog:
1、查看 oplog数据结构
命令
repl:PRIMARY> use local
repl:PRIMARY> db.oplog.rs.find().limit(1)
{ "op" : "n", "ns" : "", "o" : { "msg" : "initiating set" }, "ts" : Timestamp(1665988644, 1), "v" : NumberLong(2), "wall" : ISODate("2022-10-17T06:37:24.818Z") }
字段说明:
- ts: 8字节的时间戳,由 4字节 unix timestamp + 4字节自增计数表示。这个值很重要,在选举(如 master宕机时)新 primary时,会选择 ts最大的那个 secondary作为新 primary
- op: 1字节的操作类型
"i": insert
"u": update
"d": delete
"c": db cmd
"db":声明当前数据库 (其中 ns 被设置成为 =>数据库名称 + '.')
"n": no op,即空操作,其会定期执行以确保时效性
- ns:操作所在的 namespace
- o:操作所对应的 document,即当前操作的内容(比如更新操作时要更新的的字段和值)
- o2: 在执行更新操作时的 where条件,仅限于 update时才有该属性
2、查看 oplog的信息
通过 "db.printReplicationInfo()"命令可以查看 oplog的信息
字段说明:
- configured oplog size: oplog文件大小
- log length start to end: oplog日志的启用时间段
- oplog first event time: 第一个事务日志的产生时间
- oplog last event time: 最后一个事务日志的产生时间
- now: 现在的时间
3、查看 slave状态 **
通过 "db.printSecondaryReplicationInfo()"可以查看 slave的同步状态
- source——从库的 IP及端口
- syncedTo——当前的同步情况,延迟了多久等信息