在之前的Paxos从入门到学会Raft一文中,为了引入paxos/raft共识算法,简单地讨论了一下主从模式以及为什么主从模式不能最大限度地同时保证高可用和一致性。不过在现实场景中,常常因为基础设施不足,网络成本控制等原因,无法使用需要三中心的paxos/raft,所以我想再详细讨论下只有两中心的场景下的妥协方案。
简单回顾下上次的讨论:在两中心主从模式下,我们如果想要主从切换时不丢数据,就必须使用同步模式,即主中心写入的数据,需要同步到从中心落盘,再给客户端返回写入成功。
同步模式的困境在于,从任何一个中心的视角来看,都无法区分出“另一个中心故障”和“两中心网络断连”这两种异常情况。这导致主从模式下的failover是一定无法由程序自动进行的:
如果主中心在发现从中心故障(或断连)时自动切换至独立运行(异步)模式,那么当主中心发生故障时,从中心无法切换至独立运行模式,因为从中心无从判断主中心是真故障了,还是网络断连了(这种情况下主中心可能已切换至独立运行模式)。
反过来如果我们让从中心在发现主中心故障(或断连)时自动切换至独立运行模式,同样的道理,我们也无法处理从中心故障的情况。
这里我们面对的是一个经典的CA抉择问题,大方向上有两个选择。
第一个方向是优先保证一致性,一旦出现故障或者网络断连了就主动停止服务,由运维来选择一个中心来恢复服务。我们都知道,一旦需要人工介入,高可用性这块基本上就免谈了。还有一个可能产生麻烦的点在于在发生故障的前提下(且可能是网络故障),或许会给运维人员接入生产环境带来一定的困难,这也会进一步增加故障恢复时间。
另一个方向就是优先保证高可用。典型的做法是主中心在发现从中心故障(或断连)时,自动切换成异步模式提供服务。如前所述,一旦主中心故障,就需要人工干预来进行主备切换了。要特别注意这种情况下主备切换不仅比较tricky还有丢数据(不一致)的可能,以下两段划重点:
主备切换之前,需要先把主中心的服务给“掐掉”,因为主中心是有自动切换异步模式单独服务的机制的,如果在主备切换之后假性故障的主中心死灰复燃,两个中心同时提供服务,会产生非常严重的后果!那么怎么把主中心的服务掐掉呢?如果此时能接入主中心,可以直接停掉所有进程或者通过配置开关禁用自动切异步模式的功能;还可以通过网关、防火墙等配置断开应用和主中心数据服务的连接;另一个选项是在应用层做主备切换,保证所有应用都只连接从中心的服务。如果这些都做不到,此时做主备切换就要承担很大的风险了,建议上报给老板做决策。
主从数据可能不同步。理论上讲在同步模式下主中心发生故障,从中心一定有全量数据。但是实际上如果此时不能接入主中心检查状态,我们单看从中心无法排除这种可能性:主中心在完全故障之前,先跟从中心发生网络断连,随后自动切换异步模式并写入了一些数据。因此,做主备切换之前,除非能接入主中心并确认其没有切换过异步模式,还要承担丢数据的风险,这里同样建议您先上报老板。
工程实践中,C和A并不是非此即彼的选择题,常常有权衡的空间。在双中心主备切换的场景中,我们可以牺牲一些可用性来换一些一致性。
做法也很简单,就是给主中心切换异步模式设置一个比较大的超时时间,比如30分钟。这样当从中心故障时,主中心需要等待30分钟才能独立提供服务,牺牲了可用性。换来的一致性保证是,当主中心故障(或断连)时,如果我们在30分钟之内做主备切换,就能确定一定不丢数据。
具体的超时时间可以根据需要进行调整,很大的值其实就是一致性模式,很小的值对应的是高可用模式。看到这里熟悉Oracle的朋友们应该都会心一笑了,这其实就是DataGuard的maximize protection模式和maximize availability模式嘛。
接下来简单聊一下架构层面改进的两种思路。
第一个思路是向三中心架构推进一步。开头也说了使用paxos/raft三中心的主要问题是成本太高了,然而实际上不需要完整的三中心三副本也能达到比较好的效果。主备模式的主要缺陷在于两个数据中心的地位是完全对等的,出现网络隔离的时候无法判断对面是不是真挂了。
我们可以在第三个数据中心部署一个简单的etcd服务来扮演“仲裁者”的角色,在主从中心正常工作的时候,不需要与etcd作任何消息交换,发生故障时,哪边能连上etcd,哪边就有权切换成独立服务模式。假如主从网络断连,同时它们又同时能连接到etcd,那么主中心切换成异步模式并把状态信息通过etcd传递到从中心。
由于跟第三个数据中心之间只需要传递简单的状态信息,可以考虑使用移动网络、无线电或者卫星通信(如北斗短报文)来进一步减少成本。
另一个思路成本更低一些,不使用第三个数据中心,直接在主从中心之间建立低成本旁路通信同步状态。这时因为没有“仲裁者”了,在出现整个数据中心故障时仍然会陷入“两难”的境地,不过在发生网络故障时,主从中心可以通过旁路进行状态交换然后迅速进行异步模式切换。
最后来点主题升华哈。权衡是软件工程架构设计的最经典命题之一,绝大部分情况下都没有完美的设计,只有特定约束条件下最平衡的设计。诚然,一个又一个“不可能三角”告诉我们完美的系统是不存在的,但换个角度来看,不可逾越的鸿沟也是可以去不断逼近的极限,这就是工程师的浪漫呀!