我在讲软件可靠性时,有讲软件的容错设计(见《系统性谈谈软件可靠性——第3讲:软件可靠性设计方法》一文)。
实际上不只是软件才有容错,今天再补充讲讲容错设计。
容错设计的基本思想来源于冯·诺伊曼,他指出人的大脑细胞在人的一生中不断地死亡,令人惊奇的是这并不影响任何生理系统的正常工作。另外,包括人体在内的众多生命体都有自愈机制,例如粘膜的自行修复或再生、皮肤和肌肉以及软组织愈合等等。这种生物界的自动恢复能力如果能引用到技术领域,使系统也具有这种自修复和容忍故障的能力,就可以达到高可靠性系统的目的。这就是容错的思想。
容错技术是对故障的“容忍”,但并非是“无视”故障的处在。它首先能自动地实时检测并诊断出系统的故障,然后对故障进行决策、处理。这个过程大概可以表达如下:
图片摘自《可靠性设计与分析》一书(主编 曾声奎)
常用的容错技术实现方法有信息容错、时间容错、结构(硬件)容错和软件容错。下面分别举一些例子。
◆信息容错
在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。
为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测(部分方法还能够实现自动纠错),当且仅当检测的结果为正确时接收方才真正收下数据。如数据通信中常用CRC校验码(循环冗余校验码),奇偶校验码,海明码等。
此外,在信息的产生时,就要考虑容错。例如,容易受到外界干扰的采集数据中,不要使用一位逻辑”1”和“0”的模式来表示,而应该采用多位既非全0又非全1的模式来表示。举一个例子,一种旋转开关如下。它用五组节点来代表信息含义,避免了简单的1和0信息。
◆时间容错
时间容错是以牺牲时间来换取计算系统高可靠性的一种手段。通常为了诊断系统是否有出故障,让系统重新执行某一段程序或指令,即用时间的冗余进行故障诊断,然后根据出错的位置加以纠错从而达到容错的目的。
一般有两种方式实现时间容错,一种是有限度地降低机器的速度来增加系统可靠性。另外一种是重复执行指令或程序来消除瞬时错误带来的影响。比如下面这个程序,重复执行3次。
对于复执不成功的情况,通常的处理方法是发出中断,转入错误处理程序或者对程序进行复算,或重新组合系统,或放弃程序处理等等。
程序复算中较常用的方法是程序卷回(Program Rollback),简单地讲,是在整个程序中预先设置了若干恢复点,在各个恢复点存有在改点对应时刻的运行数据记录,供重复使用。如图所示,在遇到故障时,回滚到故障点,再重新执行程序。
我在我新电脑安装UG软件的时候,刚好遇到一个安装故障,其安装界面提示如下,回滚后它重新安装成功了,这就是典型的程序卷回。
◆结构(硬件)容错
由于数字电路的集成化程度提高,硬件的体积、重量、性能及成本大幅降低,技术上利用硬件冗余实现容错较简单可靠,所以应用十分广泛。
举一个最简单的例子,下图是一个二极管四模结构的示意图:
它可以实现:
1、任意一个二极管开路时,仍能正常工作
2、两个或者三个二极管的故障,只要不是同一支路的两个二极管短路,或者每一个支路都有一个二极管开路时,仍能正常工作。
◆软件容错
软件容错是增加程序以提高软件的可靠性的一种手段。通常采用的手段有:
1.增加用于测试检错或诊断的外加程序。
比如我之前做的这个图片归类软件《无需编程!轻松实现图片识别归类~调研、质检、营销都可应用》,在对接口的校验上,就用try-catch捕获异常:
2.用于计算机系统自动重组、降级运行的外加程序。
在许多使用计算机的领域中 ,要求其具有高可靠性,特别是用于航天领域的计算机 ,更要求其具有长时间连续运行的高可靠性。这些是普通计算机难以胜任的,必须采取容错施加以保证。
举个例子,一种带存储体行备份的模块级可降级重组双机容错系统逻辑框图如下。
该系统采用模块化结构 ,一个完整的单机由CPU、M (存储体)和 I/O 接口三个模块组成 。两个独立的单机之间用总线开关控制。当系统处于双机工作模式时,总线开关关闭, 两个单机独立工作。当系统处于降级重组的单机工作模式时,总线开关打开。图中,CL1、CL2分别是I机 、Ⅱ机的切换控逻辑,M1' 、M2'是M1、M2的行备份。BS为总线开关。
为了实现这个功能,计算机就会有一些程序去保证,比如说双机间的数据交换程序、容错管理程序。
3.一个程序用不同的语言或途径独立编写。
在讲软件可靠性时,我们提了,N-版本程序设计方法。不同的小组用许多变体(不同的设计方法,不同的算法,不同的程序设计语言,不同的编译程序,不同的实现技术,不同的设计师及程序员)实现相同的规格说明,所有变体同时进行计算,利用表决系统选择多数作为输出。
4.按一定方式将执行结果分阶段进行表决,诊断出软件故障并隔离,从而达到软件容错的目的。
在讲软件可靠性时,有谈过恢复块法,在每次模块处理结束时都要检验运行结果,一旦发现异常后,通过替代模块再次运行。可以用下面这个图表达:
从上面举的很多例子可以看出,容错在很多时候,是通过冗余来实现的,对冗余方式的选取,是容错设计首先需要考虑的问题。
容错设计前,需要对系统容许的故障类型进行全面的分析,确定故障原因、故障模式、故障类型,才能针对性地去设计,它不会实现对未覆盖故障的“容忍”。
容错设计时,通常是多种方法综合使用,以达到最优的容错能力。