MongoDB副本集故障切换期间的回滚
2024-09-22 14:48 abce 阅读(69) 评论(0) 编辑 收藏 举报每当复制集在选举中替换主节点时,旧主节点可能包含未复制到辅助节点的文档。在这种情况下,旧的主节点会回滚这些写入内容。在回滚过程中,节点将处于 ROLLBACK 状态。处于 ROLLBACK 状态的节点有资格在选举中投票。
从 4.2 版开始,当节点进入 ROLLBACK 状态时,MongoDB 会杀死所有正在进行的用户操作。
当主节点在故障切换后重新加入其副本集时,回滚会恢复前主节点上的写操作。只有当主节点接受了写操作,辅助节点在主节点停机前未成功复制写操作时,才有必要进行回滚。当主节点作为辅助节点重新加入副本集时,它会恢复或 "回滚 "其写操作,以保持与其他成员数据库的一致性。
MongoDB 会尽量避免回滚,因为这种情况很少发生。当发生回滚时,通常是由于网络分区造成的。辅助节点如果跟不上前主节点的操作吞吐量,就会增加回滚的规模和影响。
如果写操作在主服务器宕机前复制到副本集的另一个成员,且该成员对副本集的大部分成员仍然可用和可访问,则不会发生回滚。
收集回滚数据
配置回滚数据
createRollbackDataFiles 参数控制回滚过程中是否创建回滚文件。
> db.adminCommand({ getParameter: 1, createRollbackDataFiles: 1 }) { createRollbackDataFiles: true, ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1726916568, i: 1 }), signature: { hash: Binary(Buffer.from("bda9d6f7fe20bbdf720debb782564bceea36638b", "hex"), 0), keyId: Long("7353838889632530433") } }, operationTime: Timestamp({ t: 1726916568, i: 1 }) }
回滚数据
默认情况下,回滚发生时,MongoDB 会将回滚数据写入 BSON 文件。
对于数据被回滚的每个集合,回滚文件位于 <dbpath>/rollback/<collectionUUID> 目录中,文件名为
removed.<timestamp>.bson
例如,如果数据库reporting中的集合comments的数据回滚了
<dbpath>/rollback/20f74796-d5ea-42f5-8c95-f79b39bad190/removed.2020-02-19T04-57-11.0.bson
查看集合名称
要获取集合名称,可以在 MongoDB 日志中搜索回滚文件。例如,如果日志文件是 /var/log/mongodb/mongod.log,可以使用 grep 在日志中搜索 "rollback file "实例:
grep "rollback file" /var/log/mongodb/mongod.log
或者,也可以在所有数据库中循环运行 db.getCollectionInfos(),查找特定的 UUID,直到找到匹配为止。例如
var mydatabases=db.adminCommand("listDatabases").databases; var foundcollection=false; for (var i = 0; i < mydatabases.length; i++) { let mdb = db.getSiblingDB(mydatabases[i].name); collections = mdb.getCollectionInfos( { "info.uuid": UUID("20f74796-d5ea-42f5-8c95-f79b39bad190") } ); for (var j = 0; j < collections.length; j++) { // Array of 1 element foundcollection=true; print(mydatabases[i].name + '.' + collections[j].name); break; } if (foundcollection) { break; } }
回滚数据排除
如果要回滚的操作是被删除集合或删除文档,则不会将回滚写入回滚数据目录。
读取回滚数据
要读取回滚文件的内容,请使用 bsondump。
避免副本集回滚
对于副本集,写关注 { w: 1 } 只提供对主数据写操作的确认。如果主服务器在写操作复制到任何辅助服务器之前宕机,数据可能会回滚。这包括在使用 { w: 1 } 写关注提交的多文档事务中写入的数据。
日志和写关注多数
为防止已向客户端确认的数据回滚,所有投票成员应启用日志功能,并使用 { w: "majority" } 写关注,以确保写操作在返回给客户端之前,传播到大多数副本集节点。
从 MongoDB 5.0 开始,{ w: "majority" } 是大多数 MongoDB 部署的默认设置。
当 writeConcernMajorityJournalDefault 设置为 false 时,MongoDB 在写入操作ack之前不会等待w: "majority"写关注写入磁盘日志。因此,写操作可能会回滚。
回滚注意事项
用户的操作
从 4.2 版开始,当成员进入 ROLLBACK 状态时,MongoDB 会终止所有正在进行的用户的操作。
索引的构建
对于FCV是4.2的,MongoDB 会等待任何正在进行的索引构建完成后才开始回滚。
禁用"majority"
读关注会阻止修改索引的 collMod 命令回滚。如果需要回滚此类操作,必须将受影响的节点与主节点重新同步。
大小限制
MongoDB 支持以下具有不同大小限制的回滚算法:
·恢复到某个时间戳,这是默认的回滚算法。使用这种算法时,MongoDB 不会限制回滚的数据量。
·通过重新获取(Refetch)回滚,只有当配置文件中的 enableMajorityReadConcern 设置为 false 时,才会通过 Refetch 进行回滚。使用此算法时,MongoDB 最多只能回滚 300 MB 的数据。从 MongoDB 5.0 开始,enableMajorityReadConcern 设置为 true,且不可更改。
回滚运行时间限制
回滚时间限制默认为 24 小时,可使用 rollbackTimeLimitSecs 参数进行配置。
> db.adminCommand({ getParameter: 1, rollbackTimeLimitSecs: 1 }) { rollbackTimeLimitSecs: 86400, ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1726918891, i: 363 }), signature: { hash: Binary(Buffer.from("32f85ab925666561ffec530b73d70703dd3dcf3c", "hex"), 0), keyId: Long("7353838889632530433") } }, operationTime: Timestamp({ t: 1726918891, i: 363 }) }