2012年的时候,我第一次在工做中,遇到一个由于硬件的不可靠性引起的Bug。正是由于这个Bug,让我开始逐步花不少的时间,去复习回顾整个计算机系统里面的底层知识。算法
当时,我正在MediaV带领一个20多人的团队,负责公司的广告数据和机器学习算法。其中有一部分工做,就是用Hadoop集群处理全部的数据和报表业务。当时咱们的业务增加很快,因此会频繁地往Hadoop集群
里面添置机器。2012年的时候,国内的云计算平台还不太成熟,因此咱们都是本身采购硬件,放在托管的数据中里面。安全
那个时候,咱们的Hadoop集群服务器,在从100台服务器往1000台服务器时。咱们以为,像Dell这样品牌厂商的服务器太贵了,并且可以提供的硬件配置和咱们的指望也有差别。因而,运维的同窗开始和OEM厂
商合做,本身定制服务器,批量采购硬盘、内存。服务器
那个时候,你们都听过Google早期发展时,为了下降成本买了不少二手的硬件来下降成本,经过分布式的放式来保障系统的可靠性的办法。虽然咱们尚未抠门到去买二手硬件,不过当时,咱们选择购买了普通的机械硬盘,而不是企业级的、用在数据中心的机械硬盘;采购了普通的内存条,而不是带ECC纠错的服务器内存条,想着能省一点儿是一点儿。网络
突然有一天,咱们最大的、每小时执行一次的数据处理报表应用,完成时间变得比平时晚了很多。一开始,咱们并无太在乎,毕竟当时数据量天天都在增加,慢一点就慢一点了。可是,接着糟糕的运维
事情开始发生了。机器学习
一放面,咱们发现,报表任务有时候在一个小时以内执行不完,接着,偶尔整个报表任务会执行失败。因而,咱们不得不停下手头开发的工做,开始排查这个问题。分布式
用过Hadoop的话,你可能知道,做为一个分布式的应用,考虑到硬件的故障,Hadoop自己会在特定节点计算出错的状况下,重试整个计算过程。以前的报表跑得慢,就是由于有些节点的计算任务失败过,只是在
重试以后又成功了。进一步分析,咱们发现,程序的错误很是奇怪。有些数据计算的结果,好比“34+23”,结果应该是“57”,可是却变成了一个美圆符号“$”。oop
前先后后折腾了一周,咱们发现,从日志上看,一部分出错的任务都在一个固定的硬件节点上。学习
另外一方面,咱们发现,问题出如今咱们新的一批本身定制的硬件上架以后。因而,和运维团队的同事沟通近期的硬件变动,而且翻阅大量Hadoop社区的邮件组列表以后,咱们有了一个大胆的推测。编码
咱们推测,这个错误,来自咱们本身定制的硬件。定制的硬件没有使用ECC内存,在大量的数据中,内存中出现了 单比特翻转(Single-Bit Flip)这个传说中的硬件错误。
那这个符号是怎么来的呢?是因为内存中的一个整数字符,遇到了一次单比特翻转转化而来的。它的ASCII码二进制表示是0010 0100,因此它彻底可能来自0011 0100遇到一次在第4个比特的单比特翻转,也就是
从整数“4”变过来的。可是咱们也只能 推测是这个错误,而不能确信是这个错误。由于单比特翻转是一个随机现象,咱们无法稳定复现这个问题。
ECC内存的全称是Error-Correcting Code?memory,中⽂名字叫做 纠错内存。顾名思义,就是在内存里面出现错误的时候,可以本身纠正过来。
在和运维同窗沟通以后,咱们把全部本身定制的服务器的内存替换成了ECC内存,以后这个问题就消失了。这也使得咱们基本确信,问题的来源就是由于没有使用ECC内存。咱们全部工程师的开发团机在2012年,也换成了32G内存。是的,换下来的内存没有别的去处,都安装到了研发团队的开发机上。
其实,内存里面的单比特翻转或者错误,并非一个特别罕见的现象。不管是由于内存的制造质量形成的漏电,仍是外部的射线,都有必定的几率,会形成单比特错误。而内存层面的数据出错,软件工程师并不知
道,并且这个出错颇有多是随机的。赶上随机出现难以重现的错误,你们确定受不了。咱们必需要有一个办法,避免这个问题。
其实,在ECC内存发明以前,工程师们已经开始经过 奇偶校验的放式,来发现这些错误。
奇偶校验的思路很简单。咱们把内存里面的N位比特当成是一组。常见的,好比8位就是一个字节。而后,用额外的一位去记录,这8个比特里面有奇数个1仍是偶数个1。若是是奇数个1,那额外的一位就记录为1;
若是是偶数个1,那额外的一位就记录成0。那额外的一位,咱们就称之为 校验码位。
若是在这个字节里面,咱们不幸发生了单比特翻转,那么数据位计算获得的校验码,就和实际校验位里面的数据不同。咱们的内存就知道出错了。
除此以外,校验位有一个很大的优势,就是计算很是快,每每只须要遍历一遍须要校验的数据,经过一个O(N)的时间复杂度的算法,就能把校验结果计算出来。
校验码的思路,在不少地方都会用到。
比方说,咱们下载一些软件的时候,你会看到,除了下载的包文件,还会有对应的MD5这样的哈希值或者循环冗余编码(CRC)的校验文件。这样,当咱们把对应的软件下载下来以后,咱们能够计算一下对应软件的校验码,和官方提供的校验码去作个比对,看看是否是同样。
若是不同,你就不能轻易去安装这个软件了。由于有可能,这个软件包是坏的。可是,还有一种更危险的状况,就是你下载的这个软件包,多是被人植如了后们的。安装上了以后,
你的计算机的安全性就没有保障了。
不过,使用奇偶校验,仍是有两个比较大的缺陷。
第一个缺陷,就是奇偶校验只能解决遇到单个位的错误,或者说奇数个位的错误。若是出现2个位进行了翻转,那么这个字节的校验位计算结果其实没有变,咱们的校验位天然也就不能发现这个错误。
第二个缺陷,是它只能发现错误,可是不能纠正错误。因此,即便在内存里面发现数据错误了,咱们也只能停止程序,而不能让程序继续正常地运行下去。若是这个只是咱们的我的电脑,作一些可有可无的应用
,这却是无所谓了。
可是,你想一下,若是你在服务器上进行某个复杂的计算任务,这个计算已经跑了一周乃至一个月了,还有两三天就跑完了。这个时候,出现内存里面的错误,要再从头跑起,估计你心里是崩溃的。
因此,咱们须要一个比简单的校验码更好的解决方案,一个可以发现更多位的错误,而且可以把这些错误纠正过来的解决方案,也就是共程师们发明的ECC内存所使用的解决决案。
咱们不只能捕捉到错误,还要可以纠正发生的错误。这个策略,咱们一般叫做 纠错码(Error CorrectingCode)。它还有意个升级版本,叫做 纠删码(Erasure?Code),不只可以纠正错误,还可以在错误不能
纠正的时候,直接把数据删除。不管是咱们的ECC内存,仍是网络传输,乃至硬盘的RAID,其实都利⽤了纠错码和纠删码的相关技术。
想要看看咱们怎么经过算法,怎么配置硬件,使得咱们不只可以发现单个位的错误,还能发现更多位的错误,你必定要记得跟上下一讲的内容。
好了,让咱们一块儿来总结一下今天的内容。
我给你介绍了我本身亲身经历的一个硬件错误带来的Bug。因为没有采够ECC内存,致使咱们的数据处理中,出现了大量的单比特数据翻转的错误。这些硬件带来的错误,其实咱们没有办法在软件层面解决。
若是对于硬件以及硬件自己的原理不够熟悉,恐怕这个问题的解决方案仍是遥遥无期。若是你对计算机组成原理有所了解,并可以意识到,在硬件的存储层有着数据验证和纠错的需求,
那你就能在有限的时间内定位到问题所在。
进一步地,我为你简单介绍了奇偶校验,也就是如何经过冗余的一位数据,发如今硬件层面出现的位错误。可是,奇偶校验以及其余的校验码,只能发现错误,没有办法纠正错误。因此,下一讲,咱们一块儿来看看,怎么利用纠错码这样的方式,来解决问题。