前段时间忽然发现数据库文件路径下多了个rollback名字的文件夹,非常纳闷,里面竟然还有.bson后缀格式的文件,随一探究竟。
原来是在这段时间内发生过failover(主从切换),致使了某些不一致数据的丢失,这但是一个大问题啊,弄很差就是要丢数据的,
故进行了些调查研究,详述于此;供大虾们大绳们指点。mongodb
首先,rollback究竟是什么意思呢?在关系型数据库中由于有事务的概念,操做数据后在没有commit以前是能够执行rollback命令进行数据回退的。
而在单实例mongodb中,写入就写入了,删除就删除了,没有事务的概念,也没有rollback的操做,因此这里要讨论的是replicaset(复制集)的rollback数据库
以下图架构,在primary上执行写操做网络
步骤1: 客户端向Primary写入3笔数据 一、二、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架构
请看下图:测试
客户端驱动在链接mongo以后进行写操做的大体流程就是这样的,写操做会按照编号顺序进行, 当Client收到5号的response反馈后即认为写入成功,
而如何数据已写入journal files
,可是还没有oplog
同步到Secondary节点重放,若是此时发生Primary宕机,则就会形成主从之间数据不一致,即原Primary中有
刚才新写入的数据,但新选举出来的Primary却没有那部分数据,历来形成数据丢失spa
综上所述,rollback的发生,主要是Primary写入数据后还将来得及同步到secondary节点时,发生宕机事故,致使数据缺失,
经从新选举后产生新primary节点,但当原Primary从新加入集群时,因为要追随新Primary节点进行强一致性处理,因此会回滚宕机前未同步的数据。rest
那么回滚的数据跑到哪里去了呢?当rollback发生时,MongoDB将把rollback的数据以BSON格式存放到dbpath路径下rollback文件夹中,BSON文件的命名格式以下:日志
<database>.<collection>.<timestamp>.bsoncode
那么这个rollback数据如何写回到mongodb呢?咱们能够利用mongorestore命令进行基于文件的恢复操做,具体操做能够看我另一篇关于mongodump/mongorestore的文章blog
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的数据超过300M后就须要手动干预从原Primary去除灰色数据了,可是有网友测试3G多的数据也能自行rollback,
So,I'm not clear the real meaning of the Limitations