01
MongoDB PSA架构
MongoDB中,PSA架构使用的相当广泛。PSA副本集架构包含一个Primary 、Secondary、和一个Arbiter节点。其中,
Primary是副本集的主节点,负责接收业务的读写请求;Secondary是副本集中的从节点,负责从主库复制数据,并且作为数据的冗余副本保留在它自己的目录中;Arbiter节点是仲裁节点,不存储数据,只负责选举过程,参与选举的投票。官方给出的经典PSA架构图如下:
三节点的PSA架构副本集,在主节点发生宕机之后,可以利用Arbiter和另外一个数据节点,快速的推选出来新的主节点。同时由于Arbiter不存储数据,所以兼顾了数据存储的节约和数据的高可用。
但是在实际过程中,这个架构会遇到一些问题。
02
数据节点宕机会发生什么问题?
我们假设上述架构下,Secondary节点发生宕机,那么会发生以下三种情况:
1、对主库造成一定内存压力
MongoDB从3.2版本开始默认开启enableMajorityReadConcern,这就意味着MongoDB服务端需要支持客户端读取到被大多数节点收到并被确认的数据。无论客户端是否开启这个read concern级别,这个功能都是需要被支持的。
当Secondary发生宕机的时候,写入的数据无法满足被“大多数”节点接收(Arbiter不存储数据),主库内存中数据的 Majority Commit Point 无法推进,此时CheckPoint动作无法将这些数据持久化到磁盘上。如果从库迟迟没有回复,而此时主库写入很多,会造成Oplog一直增大。
为了支持业务读取,MongoDB主库需要在内存中维护这些最近 Majority Commit Point 的快照数据,所以内存写入压力会放大,内存使用也会增加,最终这些内存数据溢出,可能会被交换到磁盘上的SWAP分区,大大的影响MongoDB的性能。
2、业务写入可能会受到影响
MongoDB 5.0 版本之前,write concern参数默认值是1,表示只需要1个节点写入数据,就认为数据写入成功。但是这种情况下,如果主节点写入数据后,此时此群出现故障可能会导致写入主节点的数据被回滚,从而造成数据丢失。
从MongoDB 5.0 版本开始,这个write concern参数默认被设置成为majority,保证了数据一旦写入,就肯定不会丢失;但是与此同时,这就导致在PSA架构下,当集群中某一个数据节点出现故障的时候,无法满足majority=2,此时客户端发送的需要满足 w:majority 的请求要不超时要不永不返回的状态。影响比较严重。
3、基于上述写入的影响,发生一系列更糟糕的情况
由于数据写入失败,那么在分片集群中,进行的chunk搬迁和shard扩缩容,都会被动失败;
如果配置了changesteam来同步数据,则会导致下游数据无法定时获取。
4、隐含的数据回滚风险
假设PSA架构下,从库在t1时刻宕机之后长时间没有修复,此时主库子t2时刻再次宕机,而运维人员在不知情的情况下先启动了老的从库,那么t2-t1时间段内的主库更新,都会被回滚掉。而这个回滚操作,很可能中断在中间某个步骤,造成数据错乱,无法修复。
03
总结
如果你的MongoDB副本集是3副本,建议使用PSS的架构,也就是一个Primary,两个Secondary,虽然多占用了一些磁盘空间,但是数据多了一份冗余,而且不会遇到PSA架构下的上述问题。
如果是大于3的多副本,如果副本个数是偶数个,可以在集群中适当加入一个arbiter来进行投票,避免出现选举的平票现象,还可以增加冗余能力;
如果是大于3副本的奇数个副本,则还是不建议使用arbiter节点,因为引入arbiter在w=majority的情况下,会导致数据冗余能力下降,建议使用Secondary节点来代替arbiter