MongoDB 的Rollback讲解及避免

前言:
     前段时间突然发现数据库文件路径下多了个rollback名字的文件夹,很是纳闷,里面居然还有.bson后缀格式的文件,随一探究竟。
原来是在这段时间内发生过failover(主从切换),导致了某些不一致数据的丢失,这可是一个大问题啊,弄不好就是要丢数据的,
故进行了些调查研究,详述于此;供大虾们大绳们指点。

解释:
     首先,rollback到底是什么意思呢?在关系型数据库中因为有事务的概念,操作数据后在没有commit之前是可以执行rollback命令进行数据回退的。
而在单实例mongodb中,写入就写入了,删除就删除了,没有事务的概念,也没有rollback的操作,所以这里要讨论的是replicaset(复制集)的rollback

事故演示:
     如下图架构,在primary上执行写操作



          
步骤1: 客户端向Primary写入3笔数据 1、2、3, 经过oplog日志后同步到secondary节点上,此时各个节点数据一致
步骤2: 但当Primary节点再次被写入一笔数据4的时候,发生宕机,此时 数据4 还没来得及同步到从节点上
步骤3: 此时集群短时间关闭写操作开始竞选,经过一系列选举后有了新的primary节点,此时新Primary节点上是没有数据4的
步骤4: 新的primary承接了客户端的write请求,写入新数据 5,此时新primary的数据状态为1,2,3,5
步骤5: 原primary节点重新启动后申请加入replica member作为secondary节点,因为此时它与新primary数据不一致,
          所以就会发生rollback(回滚)动作,将数据状态恢复为1,2,3
步骤6:回滚完之后,将继续同步新primary节点的数据,之后数据状态变为1,2,3,5

rollback发生的具体过程:
请看下图   
 
      流程说明
          客户端驱动在连接mongo之后进行写操作的大致流程就是这样的,写操作会按照编号顺序进行, 当Client收到5号的response反馈后即认为写入成功,
而如何数据已写入journal files,但是尚未oplog同步到Secondary节点重放,如果此时发生Primary宕机,则就会造成主从之间数据不一致,即原Primary中有
刚才新写入的数据,但新选举出来的Primary却没有那部分数据,从来造成数据丢失
结论:
     综上所述,rollback的发生,主要是Primary写入数据后还未来得及同步到secondary节点时,发生宕机事故,导致数据缺失,
经重新选举后产生新primary节点,但当原Primary重新加入集群时,由于要追随新Primary节点进行强一致性处理,所以会回滚宕机前未同步的数据。

存放位置:
     那么回滚的数据跑到哪里去了呢?当rollback发生时,MongoDB将把rollback的数据以BSON格式存放到dbpath路径下rollback文件夹中,BSON文件的命名格式如下:
<database>.<collection>.<timestamp>.bson
 
还原数据:
     那么这个rollback数据如何写回到mongodb呢?我们可以利用mongorestore命令进行基于文件的恢复操作,具体操作可以看我另外一篇关于mongodump/mongorestore的文章
mongorestore --host <hostname:port> --db db1 --collection c2 -u admin_user -p"123456" 
--authenticationDatabase admin rollback/c2_rollback.BSON


避免策略:
     要讲避免策略那就应先讲讲Write Concern(写关注),也就是关心写操作。是在驱动的connection level进行配置,
支持一下值:
  • w:0 | 1 | n | majority | tag
  • j:1
  • wtimeout: millis
w:0      unacknowledged
驱动只是一味的进行写入操作,不会关心是否写入成功,也就是mongo不会返回操作结果

w:1        Acknowledged
看图我们很容易理解,Driver在做写入操作后会收到mongod的反馈OK还是NG,而这个反馈行为只是在确认数据被成功写入Data Buffer,Journal Buffer
后的状态,不保证数据能够被写入datafile(落盘)

J:1          Journaled
驱动写操作不仅要写入Journal Buffer,Data Buffer中,还要确认数据持久化到Journal file中后才反馈结果。
即使数据库宕机,重启后,操作已经持久化到journal中,可以完全恢复,但前提是mongod一定要开启journal参数

  w:2/n/majority          Replica Acknowledged
看到下图,你应该就明白一半了,好的,下一半让小弟再给你解释一下。
rollback的发生就是因为数据成功写入Primary,但是尚未同步到Secondary节点,此时Primary宕机,
当原Primary重新加入集群后则会发生灰色数据自行rollback的现象,那么怎么避免呢?当然就是在发送反馈信息给驱动前
确保数据已经更新到至少一个Secondary节点,不就完美解决此问题了。是的,使用w:2/n/majority的配置参数
就能实现,当然,为了防止网络问题出现阻塞等待,我们可以设置wtimeout

 
 Rollback 的限制:
官网有这样一句话:

我的理解是rollback的数据超过300M后就需要手动干预从原Primary去除灰色数据了,但是有网友测试3G多的数据也能自行rollback,
So,I'm not clear the real meaning of the Limitations

 





  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
以下是几个关于MongoDB的常见面试题及答案: 1. 什么是MongoDBMongoDB是一个开源的面向文档的NoSQL数据库,它以灵活的文档模型存储数据,支持动态查询和水平扩展。 2. MongoDB与传统关系型数据库的区别是什么? - 数据模型:MongoDB是面向文档的,而传统关系型数据库是基于表的。 - 数据结构:MongoDB使用BSON(类JSON的二进制表示)来存储数据,而关系型数据库使用表、行和列。 - 查询语言:MongoDB使用基于文档的查询语言,如find()和aggregate(),而关系型数据库使用SQL查询语言。 - 扩展性:MongoDB支持水平扩展,可以通过分片来处理大规模数据量和高并发访问。 3. MongoDB支持哪些数据类型? MongoDB支持多种数据类型,包括字符串、整数、浮点数、日期、布尔值、数组、内嵌文档和ObjectId等。 4. MongoDB如何实现高可用性? MongoDB通过复制集(Replica Set)来实现高可用性。一个复制集包含一个主节点和多个从节点,主节点处理写操作并将数据复制到从节点,以保持数据一致性。 5. 什么是索引,为什么在MongoDB中使用索引? 索引是为了加快查询速度而创建的数据结构。在MongoDB中,索引可以提高查询性能,减少扫描的文档数量,从而加快查询速度。 6. 如何在MongoDB中进行数据备份和恢复? MongoDB提供了mongodump和mongorestore命令行工具,可以用于备份和恢复数据。mongodump用于导出数据,mongorestore用于将备份数据导入到MongoDB。 7. MongoDB如何处理大量写入操作? MongoDB使用写入操作的顺序日志(Write Concern Journaling)来确保数据的可靠性和一致性。它将写入操作记录到日志中,并在写入磁盘之前应用到数据文件,以防止数据丢失。 8. 如何在MongoDB中执行聚合操作? MongoDB提供了aggregate管道操作符,可以用于执行聚合操作,如分组、筛选、排序和计算等。通过使用不同的管道阶段,可以构建复杂的聚合查询。 以上是一些关于MongoDB的常见面试题及答案。在面试中展示对MongoDB的理解和实际应用经验,能够加分。同时,建议深入学习和掌握MongoDB的各种特性和用法,以便在实际项目中充分发挥其优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值