海恩法则
德国人帕布斯·海恩提出一个在航空界关于飞行安全的法则: 每一起严重事故的背后,必然有29次轻微事故和300起未遂先兆以及1000起事故隐患,这个法则即是著名的海恩法则。猜想在飞行安全领域,海恩也是通过统计学的方法发现的这一法则,不然为什么是1:29:300:1000 这样的比例呢?
和海因里希法则一样,在其他领域的安全生产仍然有借鉴意义。我们来看2个案例,得以管窥一二。
东方网2016-11-25 09:15报道,截止11月24日早7时左右,江西省丰城市国电丰城电厂三期在建项目冷却塔施工平桥吊倒塌,事故死亡人数已上升至67人。记者还发现,该公司近年曾发生多起工人死伤的安全事故。那么,试问一家频发安全事故的公司为何还在正常经营,每次事故发生后又做了哪些改进措施?
大众日报于2012年曾报道过岱山县一个蓄水18万立方米的水库突然溃坝,洪水瞬间冲毁村庄。当地已确认遇难10人,27人受伤。多名村民接受多家媒体采访时反映,早在50天前,水库已经出现裂缝漏水,村民向当地政府反映了不止一次,但一直没人来修。有村民告诉记者,就在事发前一天,还有人去镇政府反映情况。在8月7日,岱山县三防指挥部在台风“海葵”到来前还曾信誓旦旦地称,岱山县水利部门已对全县水库、山塘、海塘等水利设施进行了全面检查,确保“危险水库空库运行”,“24小时值班,加密巡查频率,对水库安全运行情况进行密切监测,确保不因水利设施因素造成人员伤亡”。
别再用事故去验证海恩法则了,没有切实的措施或者防患于未然,或者对隐患的采取行动,发什么誓都没有用。“海恩法则”核心理论有二:一是事故的发生是量的积累的结果;二是再好的技术,再完美的规章,在实际操作层面,也无法取代人自身的素质和责任心。
回到软件行业,海恩法则和海因里希法则有非常好的指导意义。我们稍微回溯一下自己手头发生的,看到的,见到的系统故障,无不是因为所谓的简单、低级问题到导致大故障。
代码拷贝之祸
小明看到张三的代码刚好是实现了他想要的功能,于是就拷贝过来使用了。不曾想,上线之后,消息被张三负责的系统服务器接收去了,因此拷贝代码未正确修改事件标识。同时,笔者也见过另外一个拷贝代码的案例,导致金额错误的膨胀到100倍,因为拷贝者把多个processor的顺序搞反了,而让代码实际运行超出预期。拷贝无小事,必须让代码成为自己身体的一部分,足够了解。这2个案例都有很多种方法去发现问题而不至于让故障流入线上,质量防线一再失守,值得深思。除了可能的技能问题,态度和意识是首要问题。
未正确处理的返回值或异常
一般公司的编码规范都会涉及异常的正确处理问题。比如业务异常,系统重试;系统内部异常,返回失败;明确抛出异常和空字符串NULL的区别,明确抛出异常和返回数字0的区别等等。被调用方本应该抛出异常,结果返回了0,那么调用则继续按照正常的业务逻辑进行处理,就会发生超出预期的事情,比如本应扣款的账户却未扣款而产生资损。
GITLAB误删除数据库事件
前一段,Gitlab.com发生了一个大事,某同学误删了数据库,这个事看似是个低级错误,不过,因为Gitlab披露了整个处理过程,还直播了恢复过程,因此可以学习到更多的内容。一个叫YP的同学在给Gitlab的线上数据库做一些负载均衡的工作,在做这个工作时的时候突发了一个情况,Gitlab被DDoS攻击,数据库的使用飙高,在block完攻击者的IP后,发现有个staging的数据库(db2.staging)已经落后生产库4GB的数据,于是YP同学在Fix这个staging库的同步问题的时候,发现db2.staging有各种问题都和主库无法同步,在这个时候,YP同学发现db2.staging都hang在那里,无法同步,于是他想把db2.staging的数据库删除了,这样全新启动一个新的复制,结果呢,删除数据库的命令错误的敲在了生产环境上(db1.cluster),结果导致整个生产数据库被误删除。更悲催的事情发生了,在恢复的过程中,他们发现只有db1.staging的数据库可以用于恢复,而其它的5种备份机制都不可用。具体备份失败的原因,按Gitlab在docs.google.com披露的原因,备份失败原因如下,5种备份机制为:LVM快照、常规备份、自动同步、Azure备份、S3备份。
LVM快照在默认情况下每24小时做一次。在故障发生前大概6小时,YP正好手动运行了一次。
- 常规备份似乎也是每24小时做一次,不过YP还未能查清楚它们存储在何处。据JN声称,这些似乎未奏效,只生成了几个字节大小的文件。原因是pg_dump时效,PostgreSQL版本问题导致。
- Azure备份失效:已为NFS服务器启用了Azure中的磁盘快照,但是没有为数据库服务器启用Azure中的磁盘快照。
- 一旦将数据同步到试运行环境,同步过程就消除Web勾子(webhook)。除非我们可以在过去的24小时内从常规备份中获取这些数据,否则它们将丢失殆尽。
- 我们备份到S3的内容显然也没有奏效:存储桶(bucket)空空如也。
- 复制程序很不可靠,容易出错,依赖几个随机性的外壳脚本,而且缺少完备的说明文档。
具体的恢复过程先不追溯,但从5种备份机制都不可用就能发现巨大问题,不可用不是今天才发生的,而是长期以往就是如此。不可用的备份就是形同虚设。如何保障可用,如何衡量可用是生产备份过程中不得不做的事情。无独有偶,银行业必须做到的“两地三中心”如何衡量单机房故障之后的可用性,或者部分业务的可用性,没有全局分析、制定应急措施、持续演练,两地三中心在机房故障的时候无法发挥作用。
要出问题的。
日本瑞穗证券公司经纪人操作失误
2005年12月8日,日本瑞穗证券公司的一名经纪人在交易时出现重大操作失误,引发投资者恐慌并导致证券类股票遭遇重挫,东京证券交易所陷入一片混乱。而瑞穗证券已经因为这一数字输入错误在16分钟之内蒙受了高达270亿日元(约合18.5亿人民币)的损失,造成日本证券交易史上前所未有的重大事故。瑞穗证券公司一名经纪人接到一位客户的委托,要求以61万日元(约合4.19万人民币)的价格卖出1股J-Com公司的股票。
然而,这名交易员却犯了个致命的错误,他把指令输成了以每股1日元的价格卖出61万股。这时操作屏上市场价格栏中出现了输入有误的警告,但由于这一警告经常出现,操盘手忽视警告继续操作。随后,东京证交所发现错误,电话通知瑞穗证券公司操盘手立即取消交易,但取消交易操作未能成功。
一个重大故障,仅仅是一个警告指令而不能中止交易发布,是否正常?从海恩法则推导,一次重大故障会有N次小故障的暴露,那么对于金融行业,比例关系会有新的定义,可能很少有小故障,行业的特殊性决定。
如果进一步分析,该案例涉及到瑞穗证券公司相关工作人员疏忽、东京证券交易所系统存在缺陷且未能及时采取措施等问题。比如这样一个数量和价格均异常的交易委托能够顺利进入交易所交易系统而未被拒绝,其原因是该系统对此没有做前端检查。从质量角度看,工作人员不出问题的质量防线相当脆弱,而第二道质量防线即系统前端检查放弃,则无异于大门洞开,风险一直存在。
爱国者导弹误差
在美伊战争期间,有一沙漠盾牌行动,美军部署了爱国者导弹系统来拦截伊拉克的飞毛腿导弹。跟踪爱国者导弹的软件使用目标速度和当前时间,预测目标每一秒的位置。因为各种不同目标最大速度可能达到5马赫,这些计算必须相当精确。不幸的是雷达定位软件有一个致命缺陷,系统长时间运行之后,内部时间会不准,则影响对于目标物体的拦截,可能实际上目标物体进行了指定范围的攻击,但爱国者导弹系统发现不了,因为它锁定的范围是偏差的,此之谓差之毫厘谬以千里。
在2.26日这天,爱国者导弹系统运行了100个小时。当一枚伊拉克导弹锁定美国在沙特达兰的一处空军机场发射导弹时,爱国者导弹系统监测到了这一切。但在这个时刻,其内部时间误差达到0.34秒,所以当它尝试计算导弹下一个位置时,竟然在搜寻偏离导弹实际位置半公里多的空域。系统立即断定根本没有敌方导弹,并取消了拦截。导弹行进到了其目的地,造成28名士兵死亡。
如下图所示意,我们复盘一下事故的关键事件,看能有怎样的发现。
首先明确爱国者雷达系统的工作原理,拦截敌方导弹包括搜索、验证、跟踪三个环节。一旦要执行拦截动作,则有一个射程范围,会在目标物体周围炸裂为大约1000块碎片,这些碎片会飞入目标物体的运行轨道,破坏目标物体。
我们用时间轴来描述一下关键信息。其实早在事故前10几天,就有反馈关于雷达系统缺陷的报告了,但是并未引起美国军方的重视。
从上图可以看到,美国军方2.11有一次决策过程:认为爱国者导弹系统不会连续工作超过8小时,以色列军方的发现的是偶然事件。我们对照一下“海恩法则”的核心理论:
- 事故的发生是量的积累的结果
- 再好的技术,再完美的规章,在实际操作层面,也无法取代人自身的素质和责任心
以色列军方的发现是一次小事故的提示,可能以色列是在演习环境,未有重大后果。量的积累加上美国军方责任心不够,就导致了坏的结果。我们在软件研发中容易忽略所谓的小概率事件,不能在事件出现苗头的时候就扼杀,这和我们的责任心,意识有非常大的关系。衡量意识好不好的2个tips:1是以假设代替求证。比如我拷贝这段代码肯定是没有问题的,在A系统已经运行很久了;备份复制运行良好,我完全有信心。2是能否见微知著。如果出现了异常,你假设为小概率事件,甚至说只有在某条件下才会出现而掉以轻心,则终可能酿成大祸。
意识和责任心为什么这么重要呢?
一是墨菲定律,你假设的小概率事件则外部条件发生变化的时候概率可能会大幅度增加。二是质量保障体系包括预防、监控、熔断、修复等过程,不出错是不可能的,也就是预防措施是最有效,成本最低的方式,但是又最难。更多的措施要通过监控,控制范围,快速修复来解决。
同时,2.21日,爱国者项目组向美国军方发出警告:爱国者导弹系统如果长时间工作,射程发生偏离,追踪目标可能失败。这里有一个明显的问题就是长时间是多长?同样,军方未引起重视,再次证明一个大事故的背后是因为持续多次的人的疏忽或者系统症状未得到重视而累积而成。