软件可靠性理论

2023/12/3 架构软件工程

# 概念

# 1 可靠性的定义及定量描述

可靠性在生活中常常能听到,比如这个人不靠谱,也就是期待他干好的事,却掉链子,跑去玩游戏了或上班迟到啥的,这个大概意思就是不可靠,但还是可用的。和可用性的区别就是,能用但是会失效,所以就有了可靠性的概念。这里是一个可靠性的定义:在规定的条件下,在规定的时间内,对软件操作而不出现系统失效的概率。

主要有一些抽象出来的概念可参考:

  • 规定时间
  • 失效概率
  • 可靠度
  • 失效强度
  • 失效率
  • 平均无失效时间

# 2 可靠性目标

可靠性目标是指客户对软件心理满意程度的期望。建立定量的可靠性指标需要对可靠性、交付时间和成本进行平衡。通常用可靠度、故障强度和平均失效时间、故障的严重性等级等等指标来描述。

# 3 软件可靠性建模

# 影响软件可靠性的因素

从技术的角度来看,影响软件可靠性的主要因素如下。

(1)运行环境

(2)软件规模

(3)软件内部结构

(4)软件的开发方法和开发环境

(5)软件的可靠性投入

总之,有许许多多的因素影响这软件的可靠性,有些至今也无法确定他们与软件可靠性之间的定量关系,甚至定性关系也不甚清楚。

# 软件可靠性建模方法

一个好的软件可靠性模型应该具有如下重要特性。

(1)基于可靠的假设

(2)简单

(3)计算一些有用的量

(4)给出未来失效行为的好的映射

(5)可广泛应用

需要说明的是,软件可靠性是一门正在发展中的分支学科,许多来源于硬件可靠性的理论在软件可靠性研究中并不适用,有关软件可靠性的模型并不成熟,并且应用范围也非常有限,软件可靠性的定量分析方法和数学模型要在实践中不断加以验证和修正,对于不同类型的软件,模型的假设、表示公式及应用方式也有很大的区别。

# 4 软件可靠性测试

软件可靠性测试由可靠性目标的确定、运行环境的搭建、测试用例的设计、测试实施、测试结果的分析等主要活动组成。除此,还必须考虑对软件开发进度和成本的影响。

# 5 软件可靠性评价

是指选用或建立合适的可靠性数学模型,运用统计技术和其他手段,对软件可靠性测试和系统运行期间收集的软件失效数据进行处理,并评估和预测软件可靠性的过程。这个过程包含如下三个方面。

(1)选择可靠性模型

(2)收集可靠性数据没开

(3)可靠性评估和预测

# 6 软件的可靠性设计与管理

# 软件可靠性设计

可靠性设计概念被广为引用,但并没有多少人能提出非常实用并且广泛运用的可靠性设计技术。一般来说,被认可的且具有应用前景的软件可靠性设计技术主要有容错技术检错设计降低复杂度设计等技术。

# 容错设计技术

  • 恢复块设计:更细粒度的恢复代码块。
  • N版本程序设计:相同需求不同的开发过程开发出来的版本,通过多数表决。
  • 冗余设计:软件的冗余设计技术实现的原理是在一套完整的软件系统之外,设计一种不同路径、不同算法或不同实现方法的模块或系统作为备份,在出现故障时可以使用冗余的部分进行替换,从而维持软件系统的正常运行。
    • 结构冗余
      • 静态冗余:常用的有三模冗余和多模冗余。静态冗余通过表决和比较来屏蔽系统中出现的错误。例如,三模冗余是对3个功能相同,但由不同的人采用不同的方法开发出的模块的运行结果进行表决,以多数结果作为系统的最终结果。
      • 动态冗余:主要方式是多重模块待机储备,但系统检测到某工作模块出现错误时,就用一个备用的模块来顶替它并重新运行。这里须有检测、切换和恢复过程,故称其为动态冗余。每当一个出错模块被备用模块顶替后,冗余系统相当于进行了一次重构。各备用模块在待机时,可与主模块一样工作,也可不工作。前者叫做热备份系统,后者叫做冷备份系统。
      • 混合冗余
    • 信息冗余:是在实现正常功能所需要的信息外,再添加一些信息,以保证运行结果正确的方法。例如,纠错码就是信息冗余的例子。
    • 时间冗余:以重复执行指令或程序来消除瞬时错误带来的影响。
  • 集群技术
    • 负载均衡集群:使各结点的负载流量可与在服务器集群中尽可能平均合理地分摊处理。
    • 高可用性集群:为保证集群整体服务的高可用,考虑计算硬件和软件的容错性。如果高可用性集群中的某个结点发生了故障,那么将由另外的结点代替它。整个系统环境对于用户是透明的。

# 检错技术

在软件系统中,对无需在线容错的地方、或不能采用冗余设计技术的部分,如果对可靠性要求较高,故障有可能导致严重的后果。一般采用检错技术,在软件出现故障后能及时发现并报警,提醒维护人员进行处理。检错技术实现的代价一般低于容错技术和冗余技术,但它有一个明显的缺点,就是不能自动解决故障,出现故障后如果不进行人工干预,将最终导致软件系统不能正常运行。

采用检错设计技术要着重考虑几个要素:

  • 检错对象
  • 检测延时
  • 实现方式
  • 处理方式:大多数检错采用“查出故障——停止软件系统运行——报警”的处理方式,但也有采用不停止或部分停止软件系统运行的情况,这一般由故障是否需要实时处理决定。

# 降低复杂度设计

软件复杂性常分为模块复杂性和结构复杂性。模块复杂性主要包含模块内部数据流向和程序长度两个方面,结构复杂性用不同模块之间的关联程度来表示。

降低复杂度设计的思想就是在保证实现软件功能的基础上,简化软件结构,缩短程序代码长度,优化软件数据流向,降低软件复杂度,从而提高软件可靠性。

# 软件可靠性管理

可靠性管理目前还停留在定性描述的水平上,很难用量化的指标来进行可靠性管理。可靠性管理规范的制定水平和实施效果也有待提高。怎样利用有限的可靠性投入,达到预期的可靠性目标是软件项目管理者常常要面对的难题。因此,可靠性管理研究是一个长期的课题。

# 示例

这是关于C/S三层架构的一个问题,多个用户代理对同一个大粒度数据的读写操作容易造成数据覆盖的问题。

之前以为不从数据库更新数据来同步数据,而直接把编辑后的数据提交后,再静默同步本地对应的一小条记录就可以了。这样完成了功能而去掉了不必要的操作,然而两个月过去了,数据覆盖的问题仍然有段时间会经常发生,原因是知道的——就是多用户代理在同时操作。至于其中的“同时”的含义并没有深入思考,也觉得功能逻辑本身是会有这样的。

直到这一天,几个用户代理“同时”操作,对方的数据都被覆盖了,然后午休没的休息。话说,一个人的决定真的是可以白白浪费生命的呀!

我想到了如果不刷新更新数据,那么在同一个页面会在很长时间的范围内发生覆盖数据的问题。这个问题很明显会造成很不好的影响,虽然对用户代理进行权限控制,但这功能现在还没有,还遥遥无期呢!那么还有没有办法?

我知道这里边的原理和数据库的隔离性、一致性类似,并且和数据的粒度有关,这也类似原子性吧。但接口的数据是对一整块数据的,不过核心还是要及时拿最新的数据,这是解决问题的关键。这时,想起以前做表格行编辑或查看功能的时候,刚开始为了省事以为直接拿行数据来编辑或查看也行,后来很快发现这样非常不利于解耦。好了,到现在又有一个非常根本的必须的有价值的理由了:从功能上来看,也是需要从数据库获取到最新数据,这样可以减少覆盖数据发生的概率,更新成功后最好再刷新一下表格数据!

事已至此,有解决问题的思路了。当打开编辑入口的时候必须先刷新数据,然后编辑,提交数据(这里再提交数据前还可以拿最新数据来处理,不过这样复杂性更大也不利于系统可靠),提交数据后无论成功失败其实都可以选择刷新数据。

从架构、数据、用户场景、设计、工作、目标啥的多个视角来看问题,这样权衡下来可以有一个看起来合理的解决方案。

# 回顾

这里考虑的是可靠性的核心逻辑和实践。可靠性直白的意思是不出错,至少要在规定的时间范围内不出错,来看看如何做到这个。

首先知道错误是不可完全消除的,并且用来排查和修复错误的成本是有限的。基于这两点,应该清楚有个较合理的对待可靠性的态度:

  • **将重点关注重要且使用频繁的模块,应该要有更好的设计。**在这里更好的设计是,将频繁使用的模块和不经常使用的模块解耦,使用抽象层次稳定的设计,使用易测试和反馈的设计,使用足够的单元测试。另外还有冗余的容错、检错机制。软件复杂性是产生软件缺陷的重要根源,软件复杂性常分为模块复杂性(模块内部数据流向和程序长度)和结构复杂性(不同模块之间的关联)。
  • 尽量少影响生产环境,或者说bug不交付出去就不是缺陷(这真的绝了,一言难尽了)。
  • 最后仍然是要清楚其中的风险,做好风险管理、可靠性管理,利用有限的投入达到预期的可靠性目标。
更新时间: 2023/12/3 04:41:02