HDFS 3.x 纠删码介绍

本文主要内容翻译自:
https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html
个人添加了几个命令的示例。

目录

  • 目标
  • 背景
  • 架构
  • 部署
    • 集群和硬件配置
    • 配置项
    • 使用 Intel ISA-L
    • 管理命令
  • 限制

目标

复制成本高昂——HDFS中的默认3x复制方案在存储空间和其他资源(如网络带宽)上有200%的开销。但是,对于I/O活动相对较低的热数据集和冷数据集,在正常操作期间很少访问额外的块副本,但仍然消耗与第一个副本相同的资源量。

因此,一个自然的改进是使用纠删码(EC)代替复制,它提供了相同级别的容错性,存储空间更少。在典型的纠删码(EC)设置中,存储开销不超过50%。EC文件的复制因子没有意义。它始终为1,不能通过-setrep命令更改。

背景

在存储系统中,EC最显著的用途是廉价磁盘冗余阵列(RAID)。RAID通过条带化实现EC,将逻辑顺序数据(如文件)划分为较小的单元(如位、字节或块),并将连续单元存储在不同的磁盘上。在本指南的其余部分中,这种条带分布单元被称为条带单元(或单元)。对于原始数据单元的每个条带,计算并存储一定数量的奇偶校验单元,其过程称为编码。任何条带单元上的误差都可以通过基于残存数据和奇偶校验单元的译码计算来恢复。

将EC与HDFS集成可以提高存储效率,同时仍然能够提供与传统的基于复制的HDFS部署类似的数据耐久性。例如,一个具有6个块的3x复制文件将消耗6*3=18个磁盘空间块。但是,使用EC(6个数据,3个奇偶校验)部署,它将只消耗9个磁盘空间块。

架构

在EC的背景下,条带化有几个关键的优势。首先,它启用在线EC(立即以EC格式写入数据),避免转换阶段,并立即节省存储空间。在线EC还通过并行利用多个磁盘轴来提高顺序I/O性能;这在具有高端网络的集群中尤其可取。第二,它自然地将一个小文件分发给多个DataNode,并且不需要将多个文件捆绑到一个编码组中。这大大简化了文件操作,如删除、配额报告和联邦命名空间之间的迁移。

在典型的HDFS集群中,小文件可以占总存储消耗量的3/4以上。为了更好地支持小文件,在第一阶段的工作中,HDFS支持条带化(striping)的EC。将来,HDF还将支持连续的EC布局。更多信息见设计文件和 HDFS-7285 的讨论。

  • NameNode Extensions - 条带化HDFS文件逻辑上由块组组成,每个块组包含一定数量的内部块。为了减少这些附加块对Namenode的内存消耗,引入了一种新的分层块命名协议。块组的ID可以从其任何内部块的ID推断出来。这允许在块组级别而不是块级别进行管理。

  • Client Extensions - 由于可以并行地处理块组中的多个内部块,客户端的读写路径得到了增强。在input/read路径上,DFSStripedOutputStream管理一组数据流,每个DataNode在当前块组中存储一个内部块。数据流大多是异步工作的。协调器(coordinator)负责整个块组的操作,包括结束当前块组、分配新块组等。在input/read路径上,DFSStripedInputStream 将数据逻辑字节范围的请求转换为存储在DataNode上的内部块。然后它并行地发起read请求。当失败时,它发起额外的读请求进行解码。

  • DataNode Extensions - Datanode运行一个额外的ErasureCodingWorker(ECWorker)任务,用于后台恢复失败的纠删码块。Namenode检测到失败的EC块,然后选择一个DataNode进行恢复工作。恢复任务以作为心跳响应来传递。此过程与失败时如何re-replicated复制块类似。重建执行三个关键任务:

    1. 从源节点读取数据:使用专用线程池从源节点并行读取输入数据。基于EC策略,它调度对所有源目标的读取请求,并且只读取用于重建的最小输入块数。
    2. 解码数据并生成输出数据:从输入数据解码新的数据和奇偶校验块。所有丢失的数据和奇偶校验块会一起解码。
    3. 将生成的数据块传输到目标节点:一旦解码完成,恢复的数据块就会传输到目标DataNodes上。
  • Erasure coding policies - 为了适应异构工作负载,我们允许HDFS集群中的文件和目录具有不同的副本和纠删码策略。纠删码策略封装了如何对文件进行encode/decode。每个策略由以下信息片定义:

    1. EC Schema:包括一个EC组(如6+3)中的数据和奇偶校验块的数量,以及编解码器算法(如Reed Solomon、XOR)。
    2. String单元的大小。这决定了条带化读写的粒度,包括缓冲区大小和编码工作。

    策略被命名为 codec-num data blocks-num parity blocks-cell size。当前支持6种内建的策略:RS-3-2-1024k, RS-6-3-1024k, RS-10-4-1024k, RS-LEGACY-6-3-1024k, XOR-2-1-1024k 及 REPLICATION.

    复制(REPLICATION)是一种特殊策略。它只能在目录上设置,强制目录采用3x复制方案,而不是继承其祖先的纠删码策略。此策略使3x复制方案目录与纠删码目录交错成为可能。

    复制(REPLICATION)策略始终是启用状态。对于其他内置策略,默认情况下它们是不可用的。

    与HDFS存储策略类似,纠删码策略设置在一个目录上。创建文件时,它继承其最近的祖先目录的EC策略。

    目录级的EC策略只影响在目录中的新建文件。创建文件后,可以查询其擦除编码策略但不能更改。如果将一个已经编码了的文件重名到一个使用了不同EC策略的目录中,则该文件将保留其现有的EC策略。如果要将文件转换为其他EC策略需要重写其数据;应该通过复制文件(例如,通过distcp)而不是重命名文件来完成此操作。

    允许用户通过XML文件自定义EC策略,该文件必须包含以下三部分:

    1. 布局版本(layoutversion):表示EC策略XML文件格式的版本。
    2. 模式(schemas):包括所有用户定义的EC模式。
    3. 策略(policies):包括所有用户定义的EC策略,每个策略由模式ID和条带单元的大小(cell size)组成。

    在hadoop conf目录中有一个名为user_ec_policies.xml.template的EC策略XML示例文件,用户可以参考该目录。

  • Intel ISA-L Intel ISA-L代表Intel Intelligent Storage Acceleration Library(Intel智能存储加速库)。ISA-L是为存储应用程序设计的优化低级功能的开源集合。它包括为Intel AVX和AVX2指令集优化的快速块Reed-Solomon 方式的纠删码。HDFS纠删码可以利用ISA-L加速编码和解码计算。ISA-L支持大多数主流操作系统,包括Linux和Windows。默认情况下不启用ISA-L。有关如何启用ISA-L,请参阅下面的说明。

部署

集群和硬件配置

纠删码会在CPU和网络方面对集群提出额外的要求。

编码和解码工作在HDFS Client和DataNode上都会消耗额外的CPU。

纠删码要求集群中的数据节点最少与配置的EC条带宽度相同。对于EC策略RS(6,3),这意味着至少要有9个数据节点。

为了实现机架容错,纠删码化的文件也分布在机架上。这意味着在读取和写入条带化的文件时,大多数操作都是off-rack(脱离机架)的。因此,网络二分(Network bisection)带宽非常重要。

为了实现机架容错,至少具有与配置的EC条带宽度相同的机架数也是很重要的。对于EC策略RS(6,3),这意味着至少需要9个机架,最好是10或11个机架,以处理计划内和计划外停机。对于机架少于条带宽度的集群,HDFS无法保持机架容错,但仍将尝试在多个节点上分布条带文件,以保持节点级容错。

配置项

默认,所有的内建EC策略都是不可用的,除了由配置项 dfs.namenode.ec.system.default.policy 指定的策略默认是可用的。集群管理员可以基于集群规模和期望的容错性使用命令 hdfs ec [-enablePolicy -policy ] 设置可用的策略,比如,对于一个有9个rack的集群,如果设置的策略是 RS-10-4-1024k 就不会保留rack级的容错了,更适合的策略是RS-3-2-1024k 和 RS-6-3-1024k。如果管理员只在乎node级的容错,那么只要集群有14个以上的DataNode,RS-10-4-1024k策略也是合适的。

系统默认的可用策略,可以通过配置项 dfs.namenode.ec.system.default.policy 指定。使用此配置,当没有策略名作为“-setpolicy”命令中的参数传递时,将使用默认EC策略。

默认 dfs.namenode.ec.system.default.policy 的值是 RS-6-3-1024k

Reed Solomon和XOR的编解码器实现可以使用以下客户端和DataNode的配置项进行配置:默认的RS编解码器是 io.erasureCode.codec.rs.rawcoders,legacy RS编解码器是io.erasureCode.codec.rs-legacy.rawcoders,XOR的编解码器是io.erasureCode.codec.xor.rawcoders。用户也可以使用配置项自定义编解码器: io.erasurecode.codec.self-defined-codec.rawcoders,这些配置项的值都是有回退机制的编解码器名称列表。这些编解码器工厂按配置值指定的顺序加载,直到成功加载一个编解码器。默认的RS和XOR编解码器配置更喜欢纯Java的Native实现。没有RS-LEAGCY的Native编解码器实现,因此默认仅为纯Java实现。所有这些编解码器都使用纯Java实现。对于默认的RS编解码器,还有一个native实现,它利用Intel ISA-L库来提高编解码器的性能。对于XOR编解码器,也有一个native实现利用Intel ISA-L库提高编解码器性能。可以参阅“启用Intel ISA-L”一节了解更多信息。RS Legacy的默认实现是纯Java,默认的RS和XOR的默认实现是使用英特尔ISAL-L库的native实现。

DataNode上的纠删码后台恢复工作也可以通过以下的配置参数进行调整:

  1. dfs.datanode.ec.restruction.stripedread.timeout.millis - 条带读取超时时间。默认为5000 ms。
  2. dfs.datanode.ec.restruction.stripedread.buffer.size - 读服务的缓冲区大小。默认为64KB。
  3. dfs.datanode.ec.restruction.threads - DataNode用于后台重建工作的线程数。默认为8个线程。
  4. dfs.datanode.ec.restruction.xmits.weight - EC后台恢复任务与复制的块恢复相比使用的xmits的相对权重,默认值为0.5。设置为0表示禁用计算EC恢复任务的权重,也就是说,EC任务总是有1个xmit。纠删码码恢复任务的xmit取读取流数量和写入流数量之间的最大值。例如,如果一个EC恢复任务需要从6个节点读取并写入2个节点,那么它的xmits为max(6,2)*0.5=3。复制文件的恢复任务始终计为1 xmit。namenode使用 df.namenode.replication.max-streams 减去datanode上的 xmitsinprogress 总数,后者将replicated文件和ec文件中的xmits组合在一起,以将恢复任务调度到此 datanode。

使用Intel ISA-L

HDFS默认的RS编解码器的native实现利用了 Intel ISA-L库提升编码和解码计算性能。使用 Intel ISA-L 有三个步骤:

  1. 构建 ISA-L库。详细信息,参阅官方网站 https://github.com/01org/isa-l/
  2. 构建hadoop对 ISA-L的支持,请参阅源代码(building.txt)中“Build instructions for Hadoop”中的“Intel ISA-L build options”部分。
  3. 使用 -Dbundle.isal 将isal.lib目录的内容复制到最终的tar文件中。使用tar文件部署hadoop。确保ISA-L在HDFS客户机和DataNode上可用。

使用hadoop checknative命令验证hadoop是否正确检测到ISA-L。

管理命令

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>]
     [-help [cmd ...]]

下面是关于命令的详细说明:

  • [-setPolicy -path [-policy ] [-replicate]]
    设置纠删码策略到指定路径的目录上,
    path: HDFS中的一个目录,这是一个必选参数,设置的策略只会影响到新建的文件,对于已经存在的文件不会有影响。
    policyName: 指定纠删码策略的名称,如果配置项 dfs.namenode.ec.system.default.policy设置了,这个参数可以省略。路径的EC策略就会使用配置项中的默认值
    -replicate 适用于特殊的REPLICATION策略,强制目录采用 3x 复制schema
    -replicate-policy 是可选参数,二者不能同时使用

    示例:

    $ hdfs ec -setPolicy -path /tmp/ecdata
      Set RS-6-3-1024k erasure coding policy on /tmp/ecdata
    
  • [-getPolicy -path ]
    获取指定路径的目录或文件的纠删码的详细信息

    示例:

    $ hdfs ec -getPolicy -path /tmp/ecdata
    RS-6-3-1024k
  • [-unsetPolicy -path ]
    取消指定目录之前设置的纠删码策略,如果目录从祖先目录继承了纠删码策略,则unsetpolicy为no-op,也就是如果我们对一个目录执行了取消策略的操作,如果它的祖先目录设置过了策略,那么取消操作是不会生效的。在没有显式策略集的目录上取消策略不会返回错误。

    示例:

	$ hadoop fs -mkdir /tmp/ecdata/data1
	$ hdfs ec -getPolicy -path /tmp/ecdata/data1
	RS-6-3-1024k
	$ hdfs ec -unsetPolicy -path /tmp/ecdata/data1
	Unset erasure coding policy from /tmp/ecdata/data1
	$ hdfs ec -getPolicy -path /tmp/ecdata/data1
	RS-6-3-1024k
	$ hadoop fs -put test.zip  /tmp/ecdata/data1/123
	$ hadoop fs -du -s -h /tmp/ecdata/data1
	112.0 M  169.0 M  /tmp/ecdata/data1
  • [-listPolicies]
    列出所有注册到HDFS(enabled, disabled 和 removed)的EC策略,只有状态为enabled的策略才能使用setPolicy命令设置

    示例:

$ 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=DISABLED
  • [-addPolicies -policyFile ]
    添加EC策略,可以参考etc/hadoop/user_ec_policies.xml.template文件查看示例策略文件,最大的cell大小有选项 dfs.namenode.ec.policies.max.cellsize 定义,默认是4MB。当前HDFS支持添加最多64种策略,策略ID的范围是 64-127,如果已经添加了64中策略,那么后面的添加会失败。

  • [-listCodecs]
    获取系统中支持的EC codecs 和coders 的列表。coder是codec的实现。codec可以有不同的实现,也就是不同的coder。一个codec的coder按返回顺序列出。

    示例:

	$ hdfs ec -listCodecs
	Erasure Coding Codecs: Codec [Coder List]
	        RS [RS_NATIVE, RS_JAVA]
	        RS-LEGACY [RS-LEGACY_JAVA]
	        XOR [XOR_NATIVE, XOR_JAVA]
  • [-removePolicy -policy ]
    删除EC策略

  • [-enablePolicy -policy ]
    启用EC策略

    示例:

	$ hdfs ec -enablePolicy -policy XOR-2-1-1024k
	$ 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
  • [-disablePolicy -policy ]
    禁用EC策略

    示例:

	$ hdfs ec -disablePolicy -policy XOR-2-1-1024k
	Erasure coding policy XOR-2-1-1024k is disabled
	$ 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=DISABLED

限制

由于一些重大技术挑战,某些HDFS操作,即hflush, hsync, concat, setReplication, truncate 和 append ,目前并不支持EC文件。

  • append() 和 truncate() 在EC文件上会抛出IOException
  • concat() 会抛出IOException 如果文件中混合着不同的EC策略或者replicated文件。
  • setReplication() 在EC文件上是no-op(不生效)的
  • hflush() 和 hsync()在 DFSStripedOutputStream 是 no-op 的。因此调用hflush() 或者 hsync() 在一个EC化的文件上不能保证数据会被持久化。

客户端可以使用StreamCapabilities API来查询一个OutputStream是否支持hflush() 和 hsync(),如果客户端期望通常 hflush() 和 hsync() 实现数据持久化,当前最好的办法就是在一个non-erasure-coded 目录中创建常规 3x 副本文件,或者使用 FSDataOutputStreamBuilder#replicate() API在erasure-coded 目录中创建3x 副本文件。

你可能感兴趣的:(HDFS)