Hadoop:HDFS Raid 介绍
在分布式文件系统中,为了提高文件存储的可靠性,一般采用文件分Block的方法,并把每个Block的多个副本分别存储在不同的服务器上,Hadoop开源的分布式文件系统HDFS同样采用了这样的技术。但是,这样的方式会造成空间较大的浪费,HDFS每个文件的Block会有三个副本,如果文件大小为120MB,Block大小为64MB,则需要该文件会有两个Block,每个Block有三个副本,就是说一个120MB的文件会耗费360MB的HDFS存储空间(64MB*3+56MB*3),需要3倍于原文件大小的存储空间(300%)。随着HDFS集群的不断扩大,需要更多的磁盘来存储这些文件块的副本。如果一个HDFS集群达到下图所示的规模,可能任何一个公司都要考虑一下是不是该采用其他技术来弥补多副本造成的空间浪费了。
我们知道,Raid技术能够通过纠错编解码来实现文件存储的可靠性。一个磁盘的数据发生损坏,可以通过纠错编解码来恢复该数据。虽然它也会产生多余的校验码parity,但是原数据本身并不会存成多份。作为另外一种提高可靠性的理念,Raid技术也被引入到了分布式文件系统中,Google新一代文件系统Colossus便采用了Raid技术(Reed-Solomon纠错编解码)实现了更经济的可靠性,FaceBook也开源了自己基于Hadoop HDFS的Raid实现(https://github.com/facebook/hadoop-20),Hadoop社区对HDFS Raid也有专门的介绍(http://wiki.apache.org/hadoop/HDFS-RAID)。接下来,我们来介绍一下HDFS Raid相关的情况。
首先,HDFS Raid是以文件为粒度进行的空间压缩方式,它能够在保证可靠性的前提下有效地减少文件占用HDFS存储空间的大小。
熟悉传统Raid的朋友都知道"分条"(stripe)技术,HDFS Raid中也借用了这个概念,它把文件每X个Block作为一个stripe来进行编码校验,其中X就是stripe length。比如,一个文件/foo/bar有16个Block,stripe length是10的话,该文件就有2个stripe。每个stripe是一个独立的编码校验单元,编解码都是以stripe为单位的。上面提到的那个文件,第1-10块作为stripe1进行编码,第11-16块作为stripe2进行编码,生成stripe1的编码校验不需要stripe2中的Block参与,反之亦然。
目前,HDFS Raid采用了XOR和RS(Reed-Solomon)两种编码方式。
XOR编码相对而言比较简单,纠错能力也弱一些。它采用异或算法生成校验码parity,每个stripe只生成1个parity,对应上面的/foo/bar文件,两个stripe就会有两个parity Block,这两个parity Block组成一个parity文件/raidxor/foo/bar。在每个Block一个副本的情况下,如果某个stripe中丢失或者损坏了一个Block,通过XOR是可以将它恢复出来的,但是大于一个就不行了。
RS编码实现比较复杂,但是纠错能力较强,被广泛用于各种商业用途,比如CD,DVD和通信协议WiMAX。它的特点在于允许用户自定义parity长度(parity len)来达到压缩和可靠性的平衡。如果parity len = 4,会生成四个parity Block,组成/raidrs/foo/bar文件。它能够容忍同一stripe中同时丢失4个Block还能将恢复出来。HDFS Raid也主要采用这种编码方式。
需要注意的是,HDFS Raid建议将同一stripe的Block(包括parity Block)分散放置在不同的datanode上,这样避免某个datanode发生故障时,影响对这些Block的恢复,这个道理跟采用冗余备份时不能将同一Block的三个副本放在同一个datanode上的道理是一样的。
下面对冗余备份和Raid(RS编码)进行比较: (N=文件的Block数, p为单个块的损坏概率, stripe=原文件每多少块做一个stripe, parity=每个stripe有多少个parity Block, tarRepl=目标文件的副本数, metaRepl=parity文件的副本数,空间占有率=目标文件及parity文件所占空间/原文件所占空间*100%)
- 冗余方式(tarRepl=3): 文件损坏概率=O(p^3), 空间占有率=300%
- Raid RS: 文件损坏概率=O(p^(parity+1)), 空间占有率=(100*(targetRepl*N + math.ceil(N*1.0/stripe)*metaRepl*parity)/N) % = (targetRepl + math.ceil(N*1.0/stripe)*metaRepl*parity/N)*100 %. 假设我们需要将文件损坏概率至少降低一个数量级,则parity>=3。空间占有率相关的参数较多,我们来取下面的几个值:
- 由parity=3, targetrep=1, metaRepl=1, stripe=10, N=5得到,空间占有率=160%
- 由parity=3, targetrep=1, metaRepl=1, stripe=10, N=10得到,空间占有率=130%
- 由parity=3, targetrep=2, metaRepl=1, stripe=10, N=5得到,空间占有率=260%
- 由parity=3, targetrep=2, metaRepl=1, stripe=10, N=10得到,空间占有率=230%