作者:Gu Ruinan - 互联网大数据团队- Zhao Yongxiang
Erasure Coding(简称EC),是一种纠删码。EC编码能够对部分缺失的数据进行数据恢复,广泛应用于存储与通信领域。在Hadoop3.0版本中,作为一种新的冗余存储的方式引入进来。使用EC编码的方式替代原来的三副本存储,保证数据可靠性的同时可以节约存储。相应地,付出的代价是读取性能的下降,对于访问频率不高的数据,使用EC编码很合适。
vivo目前HDFS集群节点达万台级别,数据规模接近EB级别,并且业务数据规模还在以较高速度持续增长中。在推进压缩算法缓解存储压力的同时,EC编码的推进也是存储降本的一大有力手段。
1分钟看图掌握核心观点👇
一、背景
Reed-Soloman编码(简称:RS码),是EC里一种经典的编码算法。下面简单介绍一下Reed-Soloman编码过程(不涉及数学原理的详细解析)。
假设我们的输入数据以D1,D2,...D5的向量来表示,矩阵B为编码矩阵,进行编码后得到D和C组成的矩阵,其中D为数据块(data block),C为校验块(parity block)。我们的数据写入都需要经过编码后才能进行存储。
假设我们抹除掉了D1,D4,C2。
我们能通过编码矩阵得到一个用于恢复的矩阵,将这个矩阵与剩余块相乘,可得到原来完整的输入数据,再次进行编码后可恢复C2。
二、存储布局的改变
EC编码对HDFS的应用,使数据块存储的结构发生了改变。
在传统三副本的策略中,一个文件被划分为不同的块(block)进行存储,一个数据块对应三个副本(replication),每个副本存储的内容完全一致,数据的存储时连续的,这种布局称为连续块存储布局(Contigous Block Layout)。
在EC策略中,一个文件被划分为不同的块组(Block Group)进行存储,一个块组内划分为多个内部块(Internal Block),其中,内部块又分为数据块(Data Block)和校验块(Parity Block)。数据块存储文件的数据,校验块存储由数据块生成的校验内容。一个块组内,可容忍的块丢失数量与校验块数量相同,如果丢失块的数量大于校验块数量,则数据不可被恢复。
在块组中,数据并不像三副本策略一样连续存储在一个块中,而是将连续的数据拆分为多个Cell,分散存储在不同的内部块中,形成一个个条带(Stripe)。这种布局称为条带存储布局(Striped Block Layout)。
我们集群目前采用EC策略RS6-3-1024k,其中6表示块组中数据块数量,3表示块组中校验块数量,1024k表示Cell大小。
三副本是HDFS默认的冗余存储方式,优点是当有机器宕机,数据丢失时,不会影响用户的读取,补块的方式也仅仅是副本的复制,简单高效。缺点也很明显,存储的冗余度高,三副本的存储冗余度达到200%。
EC编码通过编码的存储方式,来进行冗余存储。优点是存储的冗余度低(具体的冗余度取决于不同的存储策略),可靠性高。缺点是写入需要编码,造成性能的下降(大概3-4倍),补块时间长(校验块越多,补块时间越长),读取时如果遇到DN宕机,也需要额外的资源与时间进行解码恢复。
三、HDFS EC 码应用实践
3.1 兼容性问题
3.1.1 服务端
早在2020年,EC已经在vivo的HDFS集群中投入使用。EC是Hadoop3.0后推出的新特性,要想正常使用,服务端和客户端都需要升级到3.0或以上版本。
由于离线集群规模庞大,升级的调研和实施需要耗费比较长的时间。因此,我们临时搭建了一套基于3.1版本的冷备专用集群,使用EC来存储冷备数据,如下图:
冷备集群使用3.1版本的Yarn,可以同时访问热数据与冷数据,3.1版本的HDFS专门用来存储EC编码的冷数据。
由于新增冷备集群的方案增加了集群运维的成本,架构也不够优雅,只是暂时的解决办法。在2021年,我们离线集群完成了HDFS从2.6到3.1的全面升级,正式支持EC编码,在2022年,我们完成绝大部分冷备集群的数据到离线集群的迁移,增量数据全部写到离线集群中。
3.1.2 客户端
我们没有对Client2.x客户端访问EC文件做兼容性的开发,更多是通过推动用户升级客户端来访问EC文件,例如Spark2任务切换至Spark3任务。该方案增加了用户迁移的成本,但同时也减少了HDFS侧的开发成本,用户任务逐步往Spark3迁移也更符合未来的规划。
3.2 EC 异步转换
由于EC编码会带来对文件读写性能的下降,对EC编码的定位主要应用在冷数据的存储,业务并不直接写EC数据,而是采用后台转储的方式,把三副本数据转储成EC数据。对不同业务而言,对"冷"的标准都不一致,不能用统一的标准来衡量数据的冷热。在推广EC编码的过程中,平台并不用统一的标准来"强制"把用户数据转为EC,是否转为EC的最终决定权在用户。我们向用户提供分区访问频率的数据作为参考,帮助用户来了解不同分区路径的访问频次,让用户更好地选择哪些分区转为EC编码。用户可以通过大数据开发者平台(Big data developer platform)设置x天前的数据转为EC存储,后台程序会将相应分区通过Hadoop distcp,将三副本写入到已设置EC策略的目录中,再用新目录替换掉原目录,其中目录名称不变,保证了元数据一致,用户无需修改代码。
3.3 Distcp 数据校验
先来介绍一下HDFS两种校验和的方式。
3.3.1 MD5MD5CRC
此方式为HDFS默认的校验方式,这种校验方式会进行两次MD5计算一次CRC计算,从名字就可以反映出来。
-
块级校验和:所有chunk CRC的级联的MD5值。(an MD5 of a concatenation of chunk CRCs)
-
文件级校验和:所有块校验和的级联的MD5值。(the MD5 of the concatenation of all the block checksums)
由定义可知,这种方式对于HDFS分块大小敏感,不同的分块大小块级校验和不一样,导致文件校验和也会不一样。
3.3.2 Composite CRC
Composite CRC一个新的校验和计算方式。
当计算块校验和不是简单地将chunk CRC进行级联(concatenation),而是将chunk CRC进行数学式的组合(mathematically compose),计算文件校验和时对文件所有的chunk CRC进行数学式组合。因此,对于文件校验和,该计算方式对于分块大小并不敏感。 CRC算法相关论文。
在数据进行distcp的过程中,HDFS会进行校验和校验,确保distcp的源数据与新数据一致,但正如前文所说,EC编码会带来存储布局的改变,相同的文件三副本与EC数据存储的块大小,块数量都不一致,这让HDFS默认的MD5MD5CRC的方式变得不再适用。
需要将校验方式改为COMPOSITE CRC。
可通过 dfs.checksum.combine.mode 改变校验和校验的方式(MD5MD5CRC(默认值) or COMPOSITE_CRC)。
即使distcp过程中会进行校验,为了确保万无一失,我们还会对前后的分区目录的校验和校验。(目录校验和计算方式为将目录下文件MD5值排序,再进行MD5计算)为了保证转EC前后文件的一致性,多加一道校验的"工序"是值得的。
3.4 文件损坏与修复
文件损坏与丢块是HDFS EC应用绕不开的一个话题,原因是在Hadoop EC特性新推出的过程中,有若干与文件损坏相关的bug。EC文件损坏的过程主要发生在补块阶段,计算结果的不准确导致了新补的块与原来的块内容不一致。我们在EC推广的过程中,也狠狠地踩过文件损坏的"坑"。如何避免文件损坏,如何对补块的结果进行校验,如何修复损坏文件是三个重要的需要解决的问题。
3.4.1 如何避免文件损坏
通过对社区的调研,我们打了若干的patch来解决文件损坏与丢块的问题。
3.4.2 对补块结果的校验
我们引入了HDFS-15759,Patch提供了一个对EC补块的校验功能,在DN执行补块任务时,对补块结果进行校验。如果校验失败会抛出异常,并且补块任务会进行重试。
3.4.3 EC批量校验工具
我们对开源的EC批量校验工具进行了定制化的改造,工具能够对EC目录进行批量扫描,扫描出目录中的损坏的EC文件,在此感谢Stephen O'Donnell对工具的开源。
原理大致如下,对数据块进行EC编码,通过比对新生成的校验块和原来的校验块,来验证是否存在文件损坏。如果比对通过,则没有文件损坏,如果比对不通过,则存在文件损坏。
工具支持MR,可以分布式执行,此外,也可只对一个条带进行比对,只生成校验块的第一个条带,比对与原校验块第一个条带是否一致,这些都大大提高了批量校验EC文件的效率。
工具地址:
https://github.com/sodonnel/hdfs-ec-validator
3.4.4 修复损坏文件
在我们的集群,绝大部分损坏的文件都是ORC文件,ORC文件发生损坏时,由于其元数据分布的方式,会出现元数据的损坏,ORC无法解析。
假设一个块组内,数据块编号为1~6,校验块编号为7~9,数据块1损坏,我们可以通过读取数据块2~6加上任一一个校验块,得到"完好"的文件,对于ORC文件而言,判断是否完好取决于能否正常解析。
HDFS客户端get文件的时候默认只会读取数据块,我们通过改造HDFS客户端,使我们能够读取块组内指定编号的块,通过各种排列组合,得到一个"完好"的文件,之后将"完好"的文件覆盖掉HDFS上的损坏文件,来达到文件修复的目的。
3.5 机器异构&存储策略
由于EC数据访问频率低,将EC数据存储到大存储的机器上,利用机器异构降低我们的单位存储成本。
在HDFS中,如果文件写入的路径设置了hot存储策略的目录,则会优先把文件存储到disk存储介质当中,如果设置了cold存储策略的目录,则会优先把文件存储到archive存储介质当中。
因此,当我们将大存储机器的盘都设置为Archive,并且将EC目录设置为Cold存储策略,即可将EC数据存放到大存储机器上,使TCO降低,进一步实现存储降本。
四、总结与展望
vivo的HDFS集群已存有几百PB的数据采用EC-RS6-3-1024k策略存储,相比三副本EC-RS6-3-1024k方式能带来50%的存储收益,节省了数百PB的存储空间,为公司带来了巨大的收益。目前我们推荐用户将访问频次较少的数据转为EC,因为EC会带来读取性能的下降,如何减少EC带来的读取性能下降?以及后续细化对用户数据的冷热分层,对越冷的数据采用冗余度越低的EC策略,EC补块速度优化等,都是后续继续大规模推进EC需要解决的重要难题。