在维基百科中,高可用(high availability,HA)的定义是系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。系统无中断地运行其功能的时间越长,代表系统的高可用越好。在很多开源组件中,都有保证高可用的方案。
例如,Redis的官方文档中专门有一部分用来介绍Redis的高可用方案——哨兵(sentinel),该方案的示意如图1-1所示。哨兵节点是一组独立部署的进程,每个进程会定期向Redis主节点和从节点发送命令,探测它们是否存活。如果主节点没有正确地响应命令,那么哨兵节点就会触发Redis集群的主从切换,重新为Redis集群指定一个能够正常运行的从节点作为主节点。
图1-1 哨兵高可用方案的示意
再如,在Hadoop 1.0中,用来存储集群元信息的NameNode只有一个,没有提供高可用方案。NameNode相当于整个Hadoop集群的心脏,一旦发生故障对整体系统的影响非常大,因此Hadoop 2.0提供了NameNode的高可用方案,即系统中除了存在一个正常运行的NameNode(active NameNode),还存在一个备用NameNode(standby NameNode)。正常运行的NameNode和备用NameNode之间可以通过共享存储文件来共享数据。当正常运行的NameNode发生故障时,备用NameNode会自动代替故障的NameNode,成为新的正常运行的NameNode提供给集群使用。
对于任何系统来说,保证系统的高可用是一名开发人员的首要任务,而在现实的系统运维过程中,影响系统可用性的原因有很多。下面就介绍几个重要的原因。
影响系统可用性的一个原因是系统可能随时发生灾难性的“黑天鹅”事件,这对整体系统可用性的影响是巨大的。 庞大的系统中存在海量的服务和资源,这些服务和资源之间的关系错综复杂。即使开发和运维人员在保障系统高可用方面采取了多种措施,也很难做到尽善尽美。一个小的疏漏可能就会导致系统的全盘崩溃。
例如,2022年12月18日,阿里云香港Region的可用区C出现了一次近14个小时的故障
,故障的原因简单来说就是机房里的制冷系统出现了问题,机房里4套主备制冷系统共用了一套水路循环系统,导致制冷系统无法做到主备切换,必须花3个多小时等待制冷设备供应商来现场处理;供应商来了之后,又花了2个多小时对制冷系统进行了补水排气,结果在尝试重启制冷设备的时候,发现制冷系统存在一个群控的逻辑,导致无法重启单台制冷设备。于是,供应商又花了3个多小时来解除这个群控逻辑,并且对全部4台制冷设备进行了重启。在故障发生了近11个小时之后,机房的温度终于趋于稳定了。
在整个处理过程中还发生了一个插曲,就是在整体机房温度没有恢复正常的时候,机房的一个包间竟然触发了强制消防喷淋,所以在机房温度恢复正常之后,阿里云没有对这个包间的服务器直接上电,担心服务器进水导致数据丢失,因此阿里云又不得不对触发强制消防喷淋的包间内的服务器做了数据完整性校验,这个过程又延续了3个多小时。
总结这个案例可以得出,无论是设计系统还是设计系统故障时的应急响应都需要注意以下3个关键点。
● 不能忽视系统中的单点问题。例如,制冷系统存在单点问题,虽然有主备制冷系统,但是它们共用一套水路循环系统,一旦水路循环系统发生故障,主备制冷系统都不能正常工作。
● 做好预案,且要经过完善的故障演练。预案不足或预案没有经过完善的故障演练,可能导致切换备用制冷系统不成功;又因存在群控逻辑而无法重启单台制冷设备,需要由供应商现场修改配置来解除群控逻辑,导致故障的解决时间延长了几个小时。对于一些互联网系统,尤其是“头部”互联网公司的核心系统,系统的高可用至关重要,即使出现一个小时的故障都可能带来不可估量的损失。
● 高可用策略不能只是理论上的高可用,需要能在实践中真正发挥作用。2021年,我维护的一个系统就出现了“只是理论上的高可用”的问题。当时,我维护的系统已经在云上做了多可用区部署,保证发生故障时可以把系统流量从一个可用区切换到另一个可用区,但是因为部署流量切换系统、监控系统、报警系统等多个运维系统的可用区恰好发生了故障,导致高可用策略失效。
当然,“黑天鹅”事件发生的概率非常小,可一旦发生,对于系统来说就是致命的灾难。然而无独有偶,在2023年,国内因为机房制冷系统故障导致的系统长时间故障又接连发生了2起。此类故障不仅会给公司带来巨大的经济损失,还会严重影响用户体验和伤害公司信誉等。因此,排除故障隐患、演练故障预案,是降低“黑天鹅”事件影响的必做之事。
影响系统可用性的另一个原因是突发流量。 突发流量的典型载体是以微博为代表的社交媒体,它们经常会因突发流量而出现不可用的问题。大型的社交媒体往往拥有海量的用户,极大地加快了信息流动的速度。用户可以非常便捷地在社交媒体上获取信息,一些热点事件也更容易在社交媒体上发酵,短时间内带来大量的用户访问请求,给系统带来极大的冲击,影响系统的可用性。
影响系统可用性的更重要原因是系统变更。 《SRE:Google运维解密》一书中提到:SRE的经验告诉我们,大概70%的生产事故由某种部署的变更而触发。这里提到的变更不仅仅是代码的变更,也包括数据的变更和配置的变更等。因此,开发团队需要关注变更的流程,如规定合适的变更时间、变更前准备必要的检查清单等,这部分内容将在6.5.1节详细介绍。