高可用系统的核心在于“无中断”,这要求系统在各种故障、灾难等情况下仍能提供服务。然而,无论是硬件还是软件,单一的组件都难以做到真正的“无中断”,因为硬件会老化、故障,软件则可能有 bug。外部环境的不确定性,例如断电、地震等,也会导致系统不可用。因此,高可用的解决方案往往通过“冗余”来实现,即通过多个机器或设备来保障服务不中断。

冗余的概念与挑战

冗余的本质是通过增加设备来确保服务连续。例如,一台机器不够时用两台,多个机房、通道则避免单点故障。但高可用与高性能不同,高性能的冗余目的是提升处理性能,而高可用的冗余目的是应对故障

通过冗余提升可用性时,也会引入复杂性,尤其是涉及任务分配、状态管理等方面的挑战。接下来,将从计算高可用存储高可用两个角度探讨具体问题。

计算高可用

计算高可用的关键在于无论在哪台机器上进行运算,算法和输入数据一致时,结果也应一致。因此,将业务逻辑从一台机器迁移到另一台,并不影响计算本身的正确性。但在实际设计中,任务分配的复杂性常常是计算高可用的难点。

  1. 双机架构:从单机到双机最常见的高可用方案之一,但其引入了任务分配的需求。为了实现高可用,系统需要引入一个任务分配器来调度任务。这不仅要考虑性能,还要确保连接管理的稳定性,避免连接中断导致任务分配错误。

  2. 任务分配策略:例如,双机方案中常见的有主备架构(包括冷备、温备、热备),以及主主架构。不同策略适用于不同场景,需要根据业务需求选择合适的方案。

存储高可用

相比计算,存储高可用的设计更为复杂,因为数据在不同机器间的传输不可避免地会引入延迟或不一致性。

  1. 数据传输延迟:数据从一台机器传输到另一台的过程会受到物理传输速度的限制。例如,机房内的延迟可能是毫秒级别,而跨城市的传输延迟可能达到几十毫秒。尽管这样的延迟对用户几乎没有感知,但在高可用系统中,这种延迟会导致数据在某个时刻存在不一致问题。

  2. 数据不一致的影响:以银行业务为例,假设用户的存款数据在北京机房,但查询操作被路由到上海机房。如果数据没有及时同步,用户看到的余额可能与实际不符,导致不必要的误解和投诉。数据不一致性成为存储高可用的最大挑战。

  3. 传输故障:传输线路故障时间往往较长,例如光缆断裂等情况,这些都会导致数据无法及时同步,进一步增加系统数据不一致的风险。

因此,存储高可用的难点不仅在于如何备份数据,还在于如何减少或规避数据不一致对业务造成的影响

CAP 定理与存储设计

分布式系统中的著名理论——CAP 定理,说明了在分布式环境下,无法同时满足一致性可用性分区容错性这三个属性。因此,设计高可用系统时,必须根据实际业务进行权衡与取舍。

高可用的状态决策

无论是计算高可用还是存储高可用,状态决策是核心,即系统需要准确判断当前状态是否正常。如果状态判断错误,即使有再多的冗余处理也无法确保高可用。然而,由于状态判断本身依赖于冗余系统的信息,状态决策本质上不可能做到完全正确。常见的状态决策方式有以下几种:

  1. 独裁式决策:由一个独立的决策者收集信息并做出判断。优点是不会出现决策混乱,但如果决策者本身出现故障,整个系统就无法正常决策。独裁式决策的单点问题容易导致系统的不可用。

  2. 协商式决策:两个或多个节点通过信息交换来共同决策,典型的应用场景是主备切换。这种方式的复杂性在于,当主备连接中断时,备机如何判断主机是否真的故障。如果备机错误地认为主机故障并接管主机角色,系统就会出现两个主机(双主问题)。为解决此类问题,通常会引入多条连接,但这又引发了信息取舍的问题,即当不同连接传递的信息不一致时,如何做出正确判断。

  3. 民主式决策:多个节点通过投票来做出决策,例如ZooKeeper的集群选举。民主式决策的核心是“多数取胜”,但其缺陷在于当集群的连接中断时,系统可能出现脑裂问题,即一个集群分裂为两个独立的子集群,各自选举出主机,导致系统出现两个主节点。为避免脑裂,通常会采用“投票节点数必须超过总节点数的一半”规则,尽管这能避免脑裂,但也降低了系统的可用性,因为某些情况下有效节点数量不足时,系统将无法选出主节点。

总结

高可用系统设计的核心挑战在于如何通过冗余和状态决策来保障系统的持续可用性。计算高可用相对容易实现,因为计算任务的迁移不影响逻辑一致性,但如何进行任务分配是其复杂性所在。而存储高可用面临的挑战更为严峻,尤其是在分布式系统中,数据传输延迟和不一致问题不可避免,需要通过架构设计减少数据不一致对业务的影响。

在实际应用中,状态决策是确保高可用的基础,无论是独裁式、协商式还是民主式决策,都各有优劣,设计时需要根据系统的实际需求进行取舍。通过合理的冗余设计状态决策,可以有效提高系统的可用性,但仍需承认,在任何复杂场景下,高可用系统始终面临着一定的权衡与挑战。