OplogOutOfOrder problem
线上一个Secondary节点crash,错误原因是出现了 OplogOutOfOrder 错误,也就是说Secondary 重放了一条比『已经重放过最新的 oplog』更早的操作,经过分析,发现问题是因网络分区导致出现2个 Primary 的问题导致,详细的过程如下表分析。
说明:Node2、Node1、Node0分别是优先级为2、1、0的复制集成员。
Timestamp | Node2 | Node1 | Node0 | Notes |
---|---|---|---|---|
t1 | Primary | Secondary | Secondary | Node2被选为主 |
t2 | Primary write A | Seconary sync A | Secondary sync A | Node2上写入A,并同步到 Node1、Node0 |
t3 | Primary write B | Secondary | Secondary | Node2上写入 B,但未同步到 Node1、Node0 |
t4 | Primary | Secondary | Secondary | Node2网络与 Node1、Node0隔离,发生新的选举 |
t5 | Primary | Primary | Secondary | Node1被选为主 |
t6 | Primary | Primary WRITE C | Secondary SYNC C | Node1上写入 C,同步到 Node0 |
t7 | Primary | Primary WRITE D | Secondary SYNC D | Node1上写入 D,同步到 Node0 |
t8 | Primary Write E | Primary | Secondary | Node2上写入 E, a实际上是一个耗时很长的建索引操作结束 |
t9 | Secondary | Primary | Secondary | network recovered, Node1发现 Node2的选举时间戳更早,请求Node2降级 |
t10 | Secondary | Secondary | Secondary | Node1发现 Node2优先级更高,并且oplog 足够,主动降级 |
t11 | Primary | Secondary | Secondary | Node2赢得新的选举 |
t12 | Priamry | Secondary | Secondary | Node1 Node0 从 Node2同步,先回滚 C D |
t13 | Primary | Secondary | Secondary | Node1从 Node2 同步 B E |
t14 | Primary | Secondary | Secondary | Node0从 Node2 同步 B E ,因为 Node0已经同步过 C D,时间戳比 B 更新,触发oplogOutOfOrder 错误 crash |
上述问题也提给了MongoDB 官方团队,参考https://jira.mongodb.org/browse/SERVER-25838,这个问题在『3.0及以前的版本』或『使用 protocol version 为0的3.2版本』都有可能发生,但几率很小,使用 MongoDB 的同学不用担心,我们也是因为MongoDB云数据库 用户比较多,才触发了一例;MongoDB 3.2引入了 raft 协议,避免了上述场景发生,遇到类似问题的用户可以升级到 MongoDB-3.2,并使用复制集协议protocoal version 1。
作者简介
张友东,阿里巴巴技术专家,主要关注分布式存储、Nosql数据库等技术领域,先后参与TFS(淘宝分布式文件系统)、Redis云数据库等项目,目前主要从事MongoDB云数据库的研发工作,致力于让开发者用上最好的MongoDB云服务。
都是priority惹得祸