1.3.1 容错性
我们可能永远也制造不出永不出现故障的机器。类似的,我们更加难以制造出永不出错的软件,毕竟软件的运行还在一定程度上依赖于硬件的可靠性。那么在互联网上有那么多的应用程序和服务,它们都有可能出现故障,但在很多时候,我们几乎都不能发现这些服务中断的情况,这时分布式系统的特点之一容错性就凸显出来了。在大规模分布式系统中,检测和避免所有可能发生的故障(包括硬件故障、软件故障或不可抗力,如停电)往往是不太现实的。因此,我们在设计分布式系统的过程中,就会把容错性作为开发系统的首要目标之一。这样一来,一旦在分布式系统中某个节点发生故障,利用容错机制来避免整套系统服务不可用。
那么问题来了,在考虑容错性的同时,我们是否也需要具备检测、恢复和避免故障的能力呢?没错,在设计与开发分布式系统的过程中,这些问题都需要我们进行认真的思考。对于检测故障来说,最直接的方法是校验消息或数据是否有效,但是这种方法能够覆盖的故障面很窄。而有些问题,如服务器应用程序崩溃,通过普通方法很难检测,这时我们可能就需要一套复杂完整的流程来检测服务器是否真的宕机以及服务器的节点信息,这当中涉及很多因素,如网络延迟、消息乱序等,最后,采用合适的方法通知运维人员。
故障恢复对于分布式系统设计与开发来说极其重要。当服务器崩溃后,我们需要通过一种方法来回滚永久数据的状态,确保尚未处理完成的数据不被传递到下一个状态继续处理,并解决多个节点数据可能存在的不一致性问题,这往往涉及事务性。
常见的避免故障的方法包括消息重发、冗余等。考虑到分布式系统的特性,很多计算任务被分布在不同的节点之间进行,那么其中一个难以避免的问题就是消息丢失,消息丢失的情况屡见不鲜,这几乎成为了设计分布式系统必须解决的问题,我们通常的做法是在一定超时范围内,消息不可达时对消息进行重传,在重新尝试多次后如果消息仍然不可达,才认为节点出现问题。数据冗余存储可以在一定程度上降低数据出错的概率。例如,同一份数据,我们将其存储为A和B两份,那么当单点故障发生时,A存储的数据部分丢失或全部丢失,而B存储的数据完好无损,这时候,我们就可以利用B存储的数据对数据进行恢复,避免单点故障导致的数据丢失。当然,这里我们只考虑到数据,如果把分布式系统中其他组件也考虑进来,我们就能看到更多冗余应用的案例,例如,访问某一特定节点的路由器应当还有一份冗余备份,确保当一个路由器发生故障时,消息仍然可以通过备份的路由器送达。数据库中的数据也可以利用类似的思想存储多份冗余数据,以便在某个节点数据丢失的情况下恢复数据。在消息通信的过程中,将相同的消息派发给两个以上的节点存储或处理,以避免某个节点单点故障导致消息丢失等。
冗余是设计分布式系统时必须考虑的特性之一,也是系统对外提供服务的质量的重要保证,提高用户体验,尽可能减少服务不可用时间是非常重要的。