一个商业存储系统,为了实现故障容错需要有数据冗余技术。当组成存储系统的部件(包括但不限于硬盘)出现故障时,由于存在冗余,仍然可以从其它部件完整读取数据,从而不会因为故障造成数据丢失。
通常衡量数据冗余技术的指标为数据冗余率、检错能力、纠错能力和纠删能力,定义如下:
数据冗余率:冗余后的数据容量/原始数据容量x100%
检错:能识别数据差错
纠错:能纠正数据差错
纠删:能纠错而且能删除超过纠错能力的数据
数据冗余技术分为如下几个级别:
入门级:多副本
一般人对数据冗余技术的理解就是多存几份副本,一份丢了还有其它,副本越多越不容易丢。多副本确实是一种常用的数据冗余技术,最简单但数据冗余率的代价也最高,常见的三副本存储的数据冗余率高达300%,如果要10副本则数据冗余率为1000%。
多副本不仅数据冗余率高,而且但检错纠错能力弱,无纠删能力,还有脑裂(破坏数据一致性)风险。例如,两副本模式下,如果两份数据不一致,能够检错(知道数据有差错),但不能纠错(不知道哪份是对的),这时候就称为脑裂,就相当于一个人闹神经病一样,左脑和右脑打架。在三副本模式下,可以多数判决,具备1位的纠错能力(如果只有1位数据错,可以纠正),但不具备2位的纠错能力。
当采用三副本模式时,数据可靠性大约为11个9(年化99.999999999%)。
常规级:RAID
这是企业级存储最常用的数据冗余技术。RAID是Redundant Arrays of Independent Drives的缩写,有“独立磁盘构成的具有冗余能力的阵列”之意,也称为磁盘阵列,简称盘阵,是用多块磁盘组成一个存储池的技术。
不同的RAID模式采取不同的数据冗余方式,常见的有:
高级:N+M纠删码
纠删码(Erasure Code)是一种前向纠错的分组差错控制编码,例如RS编码、BCH编码、LDPC编码等。纠删码可以用N+M来表示,即将数据用该算法编码成N+M个数据分片(Shard),每个数据分片1/N大小,只需要其中N个数据分片就能用对应的译码算法还原数据。也就是说,最多允许M个数据分片丢失也能保障数据不会丢。
纠删码会带来一定的计算开销和元数据开销,但是数据冗余率低,只有(N+M)/Nx100%,可靠性却接近M副本。例如9+3冗余的数据冗余率只有133%,但可靠性却与3副本相当,而3副本的数据冗余率高达300%,仅仅硬盘的成本就是9+3冗余编码的2倍还要多。
不仅数据冗余率低,纠删码还具备强大的检错、纠错和纠删能力,是各存储系统工程实现的理想目标。
顶级:LRC码
数据冗余编码起源于通信领域,当把一大块数据切成很多数据包来逐次传输时,这些数据包在过程中可能会出现错误或者干脆整个数据包被丢掉。为了解决这一问题,可以将原始数据帧编码成带冗余的新数据帧再进行传输。目的节点接收到足够多的数据帧后,便可解码得到原始的数据帧。比如网络的延时/丢包,就可以通过数据冗余编码得到解决。
长期以来,存储领域一直沿用的是通讯领域的纠删码,直到最近几年,学术界开始认识到存储领域与通讯领域的数据容错的需求有些差异,开始研究存储专用的数学编码。
同样是数据容错需求,在存储领域和在通讯领域有什么差异呢?原来,通讯领域的数据是实时传输的,如果传输的数据出现超出纠错能力的错误,可以丢弃后让源端重发数据包,但在存储领域,就不存在重发的机会了,因为读取数据的时候可能已经是几年以后了,到时万一发现了数据错误,也不能重新存了。为了防止数据在存储过程中逐年累计错误(即Silent Data Corruption)最终超出纠错能力,存储系统需要不断验证数据是否正确(即心跳监测)并且重建(Rebuild)错误的数据。通信是没有重建需求的(可以用重发来代替),所以通信领域使用的纠删码就没有针对重建需求的优化设计,而存储领域需要针对重建需求进行优化,这就诞生了LRC(Locally Repairable Code)编码。
在存储系统的数据重建过程中,痛点在于重建时的系统消耗很大。N+M的纠删码在重建一块盘时需要读取N块盘的数据,不仅带宽流量要有N倍的消耗,重建工程中整个存储系统的性能也将大幅下降。随着单块盘的容量越来越大,重建的时间也越来越长,重建过程对系统性能的影响也越来越大。
LRC编码着重解决存储的数据重建开销,通过适度增加一定的冗余可以大大降低重建时的开销。例如,YTFS采用的YTLRC编码方案中,与RS等传统纠删码编码方案相比,仅仅将数据冗余率从110%提高到128%,不仅检错、纠错和纠删能力有一定提升,而且数据重建的开销有一个数量级的下降。