条纹单元:官方称之为Stripe Unit,我把它隐喻为斑马身上的黑白条纹,就称每一个文件通过EC处理后的就是一个个的条纹单元。html
EC编码奇偶校验单元java
根据剩余条纹单元和奇偶校验单元恢复数据。node
一个具备6个块,3副本会消耗6 x 3 = 18个块存储空间。而EC只须要 6个Block,再加上3个奇偶校验,仅须要6 + 3 = 9个块。节省了一半的存储空间。算法
使用EC有几个重要优点:shell
基于EC的文件存储与Hadoop经典分块存储方式作了调整。apache
基于条纹的HDFS存储逻辑上是由Block Group(块组组成),每一个Block Group包含了必定数量的Internal Block(后续咱们称为EC Block)。若是一个文件有不少的EC Block,会占用NameNode较大的内存空间。HDFS引入了新的分层Block命名协议,经过Block的ID能够推断出Block Group的ID,NameNode是基于Block Group而不是EC Block级别管理。缓存
客户端读取、写入HDFS也作了调整,当以Online-EC写入一个文件时,是以并行方式来处理Block Group中的Internal Block。网络
DataNode上运行一个ErasureCodingWorker(ECWorker)任务,专门用于失败的EC Block进行后台数据恢复。一旦NameNode检测到失败的EC Block,NameNode会选择一个DataNode进行数据恢复。架构
EC编解码器是对EC Block上的条纹单元进行处理。编码器将EC Block中的多个条纹单元做为输入,并输出许多奇偶校验单元。这个过程称为编码。条纹单元和奇偶校验单元称为EC编码组。app
解码的过程就是恢复数据的过程,能够经过剩余的条纹单元和奇偶校验单元来恢复数据。
在比较不一样的存储方案时,须要考虑两个重要因素:
HDFS中副本方案的容错性为:有N个副本,就能够容忍N-1同时发生故障。存储效率为:1/N。
下面这张表格,是针对不一样的存储方案的数据容错性和存储效率。
能够看出来,XOR只能容忍一个数据块出现故障,而RS-6-三、RS-10-4容许3个、4个数据块同时出现故障。但XOR的存储效率是最高的、其次是RS-10-四、再下来是RS-6-3。而3副本的存储效率是33%。
这张图对比了连续存储和条纹存储方案在HDFS的示意图。能够明显的看到,条纹存储方案,将一个Block继续分解为一个个的条纹单元。并在一组DataNode的block中,循环写入条纹单元。基于连续存储或者条纹存储,都是支持EC的。EC的方式存储效率比较高,但增长了复杂度、以及较高消耗的故障恢复。条纹存储方案比连续存储更好的I/O吞吐量。但与传统的MapReduce本地数据读取相悖,由于数据都是跨网络存储的。读取数据须要更多的网络I/O开销。
连续存储
连续存储容易实现,读写的方式与副本方式很是相似。但只有文件很大的场景适用。例如:使用RS-10-4,一个128M的文件仍然要写入4个128M的就校验块。存储开销为400%。这种方式,客户端须要有GB级别的缓存来计算奇偶校验单元。
条纹存储
条纹存储对小文件是友好的,能够节省不少空间。条纹单元大小一般是(64KB或者1MB)。客户端只须要有几MB的缓存就能够用于计算奇偶校验单元。但这种方案,须要跨网络I/O,性能会所以降低。要提高处理效率,须要将数据转换为连续存储,但这就须要重写整个文件了。
因此文件大小决定了使用哪一种方式更合适。Cloudera作了一些调研,发现其实HDFS中小文件(少于一个EC Block Group)的使用率占整个集群的36%-97%。小文件的处理更重要。因此HDFS EC使用的是条纹存储的EC存储方案。
为了适应不一样的业务需求,在HDFS中能够针对文件、目录配置不一样的副本和EC策略。EC策略实现了如何对文件进行编码/解码方式。每一个策略包含如下属性:
EC策略命名策略:EC编码器-EC Block数量-奇偶校验Block数量-条纹单元大小
。Hadoop中内置了5种策略:
同时,默认的副本策略也是支持的。副本策略设置在目录上,这样能够前置目录使用3副本方案,指定该目录不继承EC编码策略。这样,目录中是能够切换副本存储方式的。
Replication存储方式是始终启用的,默认启用的EC策略是:RS-6-3-1024K。与Replication存储方式同样,若是父目录设置了EC策略,子文件/目录会继承父目录的EC策略。
目录级别的EC策略仅会影响在目录中建立的新文件,这也意味着就的文件不会从新进行EC编码,HDFS是使用online-EC,文件一旦建立,能够查询它的EC策略,但不能再更改
若是将已经进行EC编码的文件移动到其余EC策略的目录,文件的EC编码也不会改变。若是想要将文件转换为其余的EC策略,须要重写数据。能够经过distcp来移动数据,而不是mv。
HDFS容许用户基于XML本身来定义EC策略。例如:
<?xml version="1.0"?> <configuration> <!-- The version of EC policy XML file format, it must be an integer --> <layoutversion>1</layoutversion> <schemas> <!-- schema id is only used to reference internally in this document --> <schema id="XORk2m1"> <!-- The combination of codec, k, m and options as the schema ID, defines a unique schema, for example 'xor-2-1'. schema ID is case insensitive --> <!-- codec with this specific name should exist already in this system --> <codec>xor</codec> <k>2</k> <m>1</m> <options> </options> </schema> <schema id="RSk12m4"> <codec>RS</codec> <k>12</k> <m>4</m> <options> </options> </schema> <schema id="RS-legacyk12m4"> <codec>RS-legacy</codec> <k>12</k> <m>4</m> <options> </options> </schema> </schemas> <policies> <policy> <!-- the combination of schema ID and cellsize(in unit k) defines a unique policy, for example 'xor-2-1-256k', case insensitive --> <!-- schema is referred by its id --> <schema>XORk2m1</schema> <!-- cellsize must be an positive integer multiple of 1024(1k) --> <!-- maximum cellsize is defined by 'dfs.namenode.ec.policies.max.cellsize' property --> <cellsize>131072</cellsize> </policy> <policy> <schema>RS-legacyk12m4</schema> <cellsize>262144</cellsize> </policy> </policies> </configuration>
配置文件很容易理解,主要包含两个部分组成:
RS-legacy:遗留的,基于纯Java语言实现的EC编解码器
而HDFS默认的RS和XOR编解码器是基于Native实现的。
XOR算法
XOR(异或)算法是最简单的EC实现,能够从任意数量的数据生成1个奇偶校验位。例如:1 ⊕ 0 ⊕ 1 ⊕ 1 = 1。但针对任意数量的条纹单元仅生成一个奇偶校验位。HDFS中若是出现多个故障,这种恢复方式是不够的。XOR的容错能力为1,存储效率为75%。
若是某一个X、Y对丢失,能够经过奇偶检验位进行异或来恢复。
Reed-Solomon算法
RS算法克服了XOR算法的限制,基于线性代数运算来生成多个奇偶校验位,能够容忍多个失败。RS 算法使用生成矩阵(GT,Generator Matrix)与 m 个数据单元相乘,以得到具备 m 个数据单元(data cells)和 n 个奇偶校验单元(parity cells)的 extended codewords。RS算法的容错能力最高为n。存储效率为 m / m + n。例如:RS-6-3为67%的存储效率,而:RS-3-2为60%的存储效率。
上图能够看到,RS是使用复杂的线性代码运算来生成多个奇偶校验单元,能够容忍每一个组出现多个故障。通常生产环境都是使用RS算法。RS-k-m是将k个条纹单元与生成矩阵Gt相乘,生成具备k个条纹单元和m个奇偶校验单元。只要k + m个单元的k个可用,就能够经过剩余的条纹单元乘以Gt的倒数恢复存储失败。能够容忍m个数据单元的故障。
默认,除了dfs.namenode.ec.system.default.policy
指定的默认策略,其余的内置的EC策略都是禁用的。咱们能够根据Hadoop集群的大小、以及所需的容错属性,经过hdfs ec -enablePolicy -policy 策略名称来启用EC策略。例如:若是有5个节点的集群,比较适合的就是RS-3-2-1024k,而RS-10-4-1024k策略就不合适了。
默认dfs.namenode.ec.system.default.policy为RS-6-3-1024k。
# 读取EC Block(条纹文件)的超时时间,默认5000毫秒 dfs.datanode.ec.reconstruction.stripedread.timeout.millis # 读取EC Block的缓存大小,默认为64KB dfs.datanode.ec.reconstruction.stripedread.buffer.size # 用于DataNode重建EC Block的线程数量,默认为8个线程 dfs.datanode.ec.reconstruction.threads # EC后台恢复任务数与复制Block的Xmits权重。NameNode基于这个Xmits值来调度任务到DataNode。默认为0.5,设置为0表示禁用EC恢复任务计算权重,始终都是1 Xmits。它的值为:读取正常EC Block的数量、以及暑输出新的EC Block的最大值。例如:若是读取6个正常的EC Block,输出到两个EC Block,则Xmits值为:Max(6, 2) * 0.5 = 3。 dfs.datanode.ec.reconstruction.xmits.weight
EC相关的操做,使用hdfs ec
命令。
hdfs ec [generic options] [-setPolicy -path <path> [-policy <policyName>] [-replicate]] [-getPolicy -path <path>] [-unsetPolicy -path <path>] [-listPolicies] [-addPolicies -policyFile <file>] [-listCodecs] [-enablePolicy -policy <policyName>] [-disablePolicy -policy <policyName>] [-verifyClusterSetup -policy <policyName>...<policyName>] [-help [cmd ...]]
一、查看当前HDFS支持的ec策略
[root@node1 hadoop]# hdfs ec -listPolicies Erasure Coding Policies: ErasureCodingPolicy=[Name=RS-10-4-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=10, numParityUnits=4]], CellSize=1048576, Id=5], State=DISABLED ErasureCodingPolicy=[Name=RS-3-2-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=3, numParityUnits=2]], CellSize=1048576, Id=2], State=DISABLED ErasureCodingPolicy=[Name=RS-6-3-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=1], State=ENABLED ErasureCodingPolicy=[Name=RS-LEGACY-6-3-1024k, Schema=[ECSchema=[Codec=rs-legacy, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=3], State=DISABLED ErasureCodingPolicy=[Name=XOR-2-1-1024k, Schema=[ECSchema=[Codec=xor, numDataUnits=2, numParityUnits=1]], CellSize=1048576, Id=4], State=ENABLED
咱们看到目前个人HDFS集群上面启用了两个策略:一个是RS-6-3-1024k、一个是XOR-2-1-1024k。
二、查看当前HDFS支持的编解码器
[root@node1 hadoop]# hdfs ec -listCodecs Erasure Coding Codecs: Codec [Coder List] RS [RS_NATIVE, RS_JAVA] RS-LEGACY [RS-LEGACY_JAVA] XOR [XOR_NATIVE, XOR_JAVA]
三、设置EC编码策略。由于个人测试集群只有3个节点,因此只能使用XOR-2-1-1024k。先要将XOR-2-1-1024k启用。
-- 建立用于存放冷数据的目录 [root@node1 hadoop]# hdfs dfs -mkdir -p /workspace/feng/cold_data -- 启用XOR-2-1-1024 EC策略 [root@node1 hadoop]# hdfs ec -enablePolicy -policy XOR-2-1-1024k Erasure coding policy XOR-2-1-1024k is enabled -- 验证当前集群是否支持全部启用的或者指定的EC策略(这个命令应该是3.2.x添加的,我当前是3.1.4,还不支持这个命令) -- hdfs ec -verifyClusterSetup -policy XOR-2-1-1024k -- 设置冷数据EC存储策略 [root@node1 hadoop]# hdfs ec -setPolicy -path /workspace/feng/cold_data -policy XOR-2-1-1024k Set XOR-2-1-1024k erasure coding policy on /workspace/feng/cold_data -- 查看冷数据目录的存储策略 [root@node1 hadoop]# hdfs ec -getPolicy -path /workspace/feng/cold_data XOR-2-1-1024k
[root@node1 software]# hdfs dfs -put hadoop-3.1.4.tar.gz /workspace/feng/cold_data 2021-01-16 14:23:28,681 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
此处,Hadoop警告提示,当前个人操做系统平台,不支持ISA-L,默认RS、XOR使用的是Native方式进行编解码,会基于Intel的ISA-L加速编解码。
咱们来查看下HDFS文件的Block的信息:
[root@node3 subdir2]# hdfs fsck /workspace/feng/cold_data/hadoop-3.1.4.tar.gz -files -blocks
咱们看到文件是以XOR-2-1-1024k进行EC编码,而且有两个Block。总共有两个EC Block Group。
0. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854775232_2020 len=268435456 Live_repl=3 1. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854775216_2021 len=38145321 Live_repl=3
总共的EC Block Group = 306580777字节,与原始的数据文件相等。
Erasure Coded Block Groups: Total size: 306580777 B Total files: 1 Total block groups (validated): 2 (avg. block group size 153290388 B) Minimally erasure-coded block groups: 2 (100.0 %) Over-erasure-coded block groups: 0 (0.0 %) Under-erasure-coded block groups: 0 (0.0 %) Unsatisfactory placement block groups: 0 (0.0 %) Average block group size: 3.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 (0.0 %) FSCK ended at Sat Jan 16 16:59:46 CST 2021 in 1 milliseconds
原始文件大小:
[root@node1 software]# ll hadoop-3.1.4.tar.gz -rw-r--r-- 1 root root 306580777 Sep 25 09:29 hadoop-3.1.4.tar.gz
咱们能够观察看到当前的Block Group大小为:256MB。而个人HDFS集群配置的dfs block size是:128MB。
<property> <name>dfs.blocksize</name> <value>134217728</value> <final>false</final> <source>hdfs-default.xml</source> </property>
由于当前的Block size是128MB,而EC的策略是:XOR-2-1,也就是一个Block Group 2个Block,因此Block Group的大小就是256MB了。
假设如今须要将一个3副本存储方式的文件,迁移到配置了EC策略的目录中。
-- 建立一个用于测试的数据目录 hdfs dfs -mkdir /workspace/feng/test_data -- 上传一个测试文件 hdfs dfs -put hbase-logs.zip /workspace/feng/test_data -- 启动YARN start-yarn.sh -- 使用distcp移动到EC策略的目录中(此处要跳过检验和,由于使用EC编码确定校验失败) hadoop distcp -update -skipcrccheck /workspace/feng/test_data/hbase-logs.zip /workspace/feng/cold_data
能够对比下该文件的block数据:
3副本方式文件
[root@node1 hadoop]# hdfs fsck /workspace/feng/test_data/hbase-logs.zip -files -blocks Connecting to namenode via http://node1:9870/fsck?ugi=root&files=1&blocks=1&path=%2Fworkspace%2Ffeng%2Ftest_data%2Fhbase-logs.zip FSCK started by root (auth:SIMPLE) from /192.168.88.100 for path /workspace/feng/test_data/hbase-logs.zip at Sat Jan 16 19:43:39 CST 2021 /workspace/feng/test_data/hbase-logs.zip 6970734 bytes, replicated: replication=3, 1 block(s): OK 0. BP-538037512-192.168.88.100-1600884040401:blk_1073742800_2023 len=6970734 Live_repl=3 Status: HEALTHY Number of data-nodes: 3 Number of racks: 1 Total dirs: 0 Total symlinks: 0 Replicated Blocks: Total size: 6970734 B Total files: 1 Total blocks (validated): 1 (avg. block size 6970734 B) Minimally replicated blocks: 1 (100.0 %) Over-replicated blocks: 0 (0.0 %) Under-replicated blocks: 0 (0.0 %) Mis-replicated blocks: 0 (0.0 %) Default replication factor: 3 Average block replication: 3.0 Missing blocks: 0 Corrupt blocks: 0 Missing replicas: 0 (0.0 %) Erasure Coded Block Groups: Total size: 0 B Total files: 0 Total block groups (validated): 0 Minimally erasure-coded block groups: 0 Over-erasure-coded block groups: 0 Under-erasure-coded block groups: 0 Unsatisfactory placement block groups: 0 Average block group size: 0.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 FSCK ended at Sat Jan 16 19:43:39 CST 2021 in 1 milliseconds The filesystem under path '/workspace/feng/test_data/hbase-logs.zip' is HEALTHY
EC编码后的文件
[root@node1 hadoop]# hdfs fsck /workspace/feng/cold_data/hbase-logs.zip -files -blocks Connecting to namenode via http://node1:9870/fsck?ugi=root&files=1&blocks=1&path=%2Fworkspace%2Ffeng%2Fcold_data%2Fhbase-logs.zip FSCK started by root (auth:SIMPLE) from /192.168.88.100 for path /workspace/feng/cold_data/hbase-logs.zip at Sat Jan 16 19:42:51 CST 2021 /workspace/feng/cold_data/hbase-logs.zip 6970734 bytes, erasure-coded: policy=XOR-2-1-1024k, 1 block(s): OK 0. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854774560_2128 len=6970734 Live_repl=3 Status: HEALTHY Number of data-nodes: 3 Number of racks: 1 Total dirs: 0 Total symlinks: 0 Replicated Blocks: Total size: 0 B Total files: 0 Total blocks (validated): 0 Minimally replicated blocks: 0 Over-replicated blocks: 0 Under-replicated blocks: 0 Mis-replicated blocks: 0 Default replication factor: 3 Average block replication: 0.0 Missing blocks: 0 Corrupt blocks: 0 Missing replicas: 0 Erasure Coded Block Groups: Total size: 6970734 B Total files: 1 Total block groups (validated): 1 (avg. block group size 6970734 B) Minimally erasure-coded block groups: 1 (100.0 %) Over-erasure-coded block groups: 0 (0.0 %) Under-erasure-coded block groups: 0 (0.0 %) Unsatisfactory placement block groups: 0 (0.0 %) Average block group size: 3.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 (0.0 %) FSCK ended at Sat Jan 16 19:42:51 CST 2021 in 1 milliseconds
基于副本冗余方式和EC方式共存。
参考文献: