前言

本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系

正文

概述

HDFS 为了提高可靠性,采用了“暴力”的三副本技术,这就带来了存储成本的问题。业界一直在探索如何降低存储成本。
传统的 RAID 技术就被很自然地借鉴过来与 HDFS 相结合。
通过结合 RAID 的 纠删码(Erasuredcode)技术,存储成本从原来的 HDFS 默认的3倍降低到1.4倍。
从 Hadoop3.x 开始 HDFS 就已经使用文件纠删码技术(ErasuredCode)代替三副本机制了。

纠删码(ErasuredCode/EC)

原理

纠删码常见的有三类:Reed-Solomen 类、级联低密度纠删码和数字喷泉码。
这里只简单介绍下目前广泛应用的 Reed-Solomen 类纠删码。

从纠刑码的基本形态来看,它是N个数据+M个校验的结构,其中数据和校验的N和M值都能够按照一定的规则设定。

在1~M个数据块(数据或校验均可)损坏的情况下,整体数据仍然可以通过计算剩余数据块上的数据得出,整体数据不会丢失,存储仍然可用。

在这里插入图片描述

从图中可以看出,纠删码和RAID技术有些类似,一个条带(Stripe)是由多个数据块(Strip) 构成的,分为数据块和校验块。

但与 RAID5、 RAID6 不同的是,纠删码从功能上来看最大的区分特点是校验和数据的比例可按N+M可调整,并且校验块数量不再受限于两个,典型的如12+4、6+3等。

关于 RAID 技术请参考我的这篇博客——一篇文章搞懂 RAID 技术是什么

纠删码的演化:RS→LRC

纠删码通过技术含量较高的算法,提供和副本近似的可靠性,同时减小了额外所需冗余设备的数量,提高了存储设备的利用率。

但纠删码所带来的额外负担主要是计算量和数倍的网络负载

尤其是在出现硬盘故障后,重建数据将耗费大量的CPU资源,而且计算一个数据块需要通过网络读出N倍的数据并传输,所以网络负载也有数倍甚至数十倍的增加。

从整体来看,若采用纠删码技术,则能够得到希望的容错能力和存储资源利用率,但是需要接受一定的数据重建代价,二者之间需要进行平衡。

那么,有没有优化改善的空间呢?

如果仔细分析故障出现的原因,则会很容易发现两个特征。

  1. 所有的故障都将导致同样的重建代价,无论是一个盘还是M个盘。
  2. 单个磁盘出现故障的概率远远大于多个磁盘同时出现故障的概率,通常在90%以上。

因此,优化的思路自然聚集到更容易出现的单个磁盘故障上来。

如何更有效地处理这种概率较大的事件呢?

最佳的解决方案是分组,把单个磁盘故障的影响范围缩小到各个组内部,当磁盘出现故障时,在该组内部解决,在恢复过程中读组内更少的盘,跑更少的网络流量,从而减小对全局的影响。

LRC

LRC(Locally Repairable Codes)意为局部校验编码,其核心思想为:

将校验块分为全局校验块和局部校验块,在故障恢复时分组计算。

以微软 Azure 的云存储(Windows Azure Storage)实现为例:

  1. 它采用LRC(12,2,2)编码,12个数据块为一组编码,并进一步将这12个数据块平均分为两个本地组,每个本地组包括6个数据块,并分别计算出一个局部校验块,之后把所有12个数据块计算出两个全局校验块。
  2. 当发生任何一个数据块错误时,只需将本地组内的数据和校验块用于计算,即可恢复出原始数据。
  3. 恢复代价(通过网络传输的数据块数量)就由传统RS(124)编码的12变为6,恢复过程的网络1O开销减半,同时空间冗余率保持不变,仍为(12+2+2)/12=1.33

总结

相对于副本而言,纠删码(Erasure Code)的编码技术无疑对存储空间利用率带来很大提升,但由于引入额外的编码、解码运算,对分布式系统的计算能力和网络都有一定的额外要求。简单地理解就是硬件性能要升级,网络环境也要升级,升级的代价在现阶段还是一笔不小的预算。

而由于性能损失的原因,用在本身压力已经很大、很“热”的在线存储系统明显不是很合适, 所以目前大多数系统还是把Erasure Code用于冷数据的离线处理阶段。

LRC编码由于减少了网络1O0传输的数据量,所以参与数据恢复运算的数据量和重建时间基本上能够缩短一倍,但这是以牺牲可靠性和空间利用率为代价的。

HDFS RAID(Facebook)

  1. HDFS RAID 方案是 Facebook 在 Hadoop0.20-append 分支上做的,为了不引入复杂度,基于 HDFS,没有修改 HDFS,只支持离线(异步)EC。
  2. RAID Node定期扫描配置发现需要转换成EC的文件转换过程可以本地计算,也可以通过 MapReduce 任务来计算。
  3. RAID Node 内部有一个 BlockFixer 线程定期检查被配置成 EC 的文件路径,如果文件有丢失或者腐化的 Block,则需要本地重算或者通过 MapReduce Job来重算,然后将生成的 Block 插入文件系统中。
  4. 客户端方面不需修改任何代码,只需修改配置,告诉它使用的文件系统是 DistributedRaidFileSystem。
  5. 它封装了 DFSClient,截获 DFS Client 的请求,当 DFS Client 抛出 ChecksumException 或者 Block MissingException 时,DRFS 捕获这些异常,定位到相应的 Parity File,然后重新计算出丢失的 Block,随后返回给客户端。

HDFS RAID 整体结构

HDFS RAID的实现(Facebook的实现)主要是在现有的HDFS上增加了一个包装 Contrib,如图所示。之所以不在HDFS上直接修改,原设计者的解释是HDFS的核心代码已经够复杂了不想让它更复杂

在这里插入图片描述

  1. 从使用的角度看, HDFS RAID的使用场景主要有两个:RAID 数据管理和 RAID 数据读取。
  2. RAID Node是 HDFS RAID 中除 NameNode 和 ResourceManager 之外的第三个 MasterNode,主要用于接收 Client 端的RPC请求和调度各守护线程完成数据的 RAID 化和数据修复、 Parity 文件删除等操作。

RAID 和 unRAID 流程详解

数据 RAID 化

文件数据的RAID化有两种场景

  1. 通过 RAID Shell执行 raidFile 命令触发;
  2. TriggerMonitor 线程周期性地扫描 Policy,根据新的配置信息进行相应的 RAID 化。

损坏数据的恢复

触发场景
  1. Client 端使用 DRFS 读取数据发生数据丢失或损坏延长。
  2. RAID Node 上的 BlockIntegrityMonitor,周期性地获取 Block 数据发现数据异常时
  3. 通过 RAID Shell 执行 fixblock 时
Block 读取时修复损坏数据的流程
  1. 在 Client 端配置 DRFS 并使用 DFS 作为内置 FS 的情况下,当通过 FS.open 获取文件 InputStream 时,返回一个 ExtFSDataInputStream 实例。
  2. 通过该 InputStream 读取数据时,首先通过内置的 DFS 读取响应的 Block,正常情况下返回需要的数据。
  3. 当内置的 DFS 读取 Block 时,若跑出 CorruptionException 或 DecomissionException,则会被 ExtFSDataInputStream 捕获。
    通过调用 RaidNode.unRaidCorruptionBlock() 方法来获取一个恢复的 Block,并从该 Block 读取数据。
Block Monitor线程修复

RAID Node 上的 BlockIntegrityMonitor 线程会通过文件检查工具检查系统中冲突或失效的数据,然后通过 BlockCopier 和 BlockFixer 线程周期性地对这些数据进行修复。

在 Local模式下,修复过程在 RaidNode 上执行;而在 Dist 模式下,修复过程通过提交Job的方式交由集群完成。

HDFS-7285

  1. 集成 EC 在 HDFS 中

HDFS-7285 和 HDFS RAID 不同,它将编码过程集成到 HDFS 内部,需要对整个 HDFS 内部实现进行改造,包括 DataNode、 NameNode及 DFS Client。该方案同时支持在线和离线 EC。

  1. 小结:HDFS-7285 比 HDFS RAID 更全面、性能更好,在线 EC 可以立即降低存储成本。

Ozone

HDFS是应用级的块存储,为了支持非文件性质的系统数据, Hortonworks 改进了HDFS,将块存储和对象存储融合,提出 Ozone,将HDFS从文件系统扩展到更复杂的企业应用。

过去,HDFS架构将元数据管理与数据存储分离成两个相互独立的层。

文件数据存储在包含有上千个存储服务器(节点)的存储层,而元数据存储在文件元数据层。

HDFS的这种分离方式使得应用直接从存储磁盘读写数据时能够获得很高的吞吐量扩展空间。

Ozone使得HDFS块存储层能够进一步支持非文件性质的系统数据,而HDFS的文件块架构也将支持存储键值和对象。

与HDFS的名称空间元数据类似, Ozone的元数据系统也基于块存储层, 但是 Ozone的元数据将被动态分配,支持大量的 Bucket Space。

Hortonworks认为,HDFS将自然进化成一个完整的企业大数据存储系统,而 Ozone也将以 Apache 项目(HDFS-7240)的方式开源。

vSAN

HDFS是根据 Google 的论文启发而发明的块存储,但是 HDFS 应该理解为应用级的存储,程序完全构建在 OS 普通用户态空间里,存储的可靠性靠“暴力”的三副本来保证。

访问 HDFS 需要使用专门的接口,因此 HDFS 只适合在 Hadoop 领域使用简单的块存储软件,并没有存储很多企业特性, 如快照、重复数据消除等。

传统的存储都构筑在专门的SAN硬件上,通信接口也采用SAS等存储专有接口,专有服务器带来的成本高、扩展性差等缺陷越来越不被客户所接受。

随着分布式技术的发展,一些专门做存储的厂商自然而然地想到用通用服务器来做存储,于是就有了一系列解决方案,最有名的是 Vmware的Virtual SAN。

Hadoop 3.x 文件纠删码技术

在EC背景下,striping 有几个关键优势。

首先,它启用了在线EC(立即以EC格式写入数据),避免了转换阶段,并立即节省存储空间。

在线EC还通过并行利用多个磁盘主轴来提高顺序I/O性能;这在具有高端网络的集群中尤为可取。

其次,它自然地将一个小文件分发给多个DataNodes,并消除了将多个文件捆绑到单个编码组中的必要性。这大大简化了文件操作,如删除、配额报告和联邦命名空间之间的迁移。

在典型的HDFS集群中,小文件可以占总存储消耗的四分之三以上。为了更好地支持小文件,在第一阶段的工作中,HDFS支持带条纹的EC。

未来HDFS还将支持连续的EC布局。有关更多信息,请参阅HDFS-7285的设计文档和讨论。

NameNode扩展

Striped HDFS 文件在逻辑上由块组组成,每个块组包含一定数量的内部块。

为了减少这些额外块的NameNode内存消耗,引入了一种新的分层块命名协议。

块组(block group)的ID可以从其任何内部块的ID推断。

这允许在块组而不是块级别进行管理。

客户端扩展

客户端读写路径被增强,以并行处理块组中的多个内部块。

在输出/写入路径上,DFSStripedOutputStream 管理一组数据流,每个数据节点一个,在当前块组中存储一个内部块。

数据流大多异步工作。协调员(coordinator)负责整个块组的操作,包括结束当前块组、分配新的块组等。

在输入/读取路径上,DFSStripedInputStream 将请求的数据逻辑字节范围转换为存储在 DataNodes 上的内部块。

然后,它并行发布读取请求。失败后,它会发出额外的读取请求进行解码。

DataNode扩展

DataNode运行一个额外的 ErasureCodingWorker(ECWorker)任务,用于后台恢复失败的 Erasure 编码块。

失败的EC块由NameNode检测,然后选择数据节点进行恢复工作。恢复任务作为心跳响应传递。

这个过程类似于复制的块在失败时如何复制。

重建时将执行三项关键任务

  1. 从源节点读取数据:使用专用线程池从源节点并行读取输入数据。基于EC策略,它将读取请求调度到所有源目标,并只读取用于重建的最小输入块数。
  2. 解码数据并生成输出数据:从输入数据解码新数据和奇偶校验块。所有缺失的数据和奇偶校验块一起解码。
  3. 将生成的数据块传输到目标节点:解码完成后,恢复的块将传输到目标数据节点。

文件纠删码策略

为了适应异构的工作负载,我们允许 HDFS 集群中的文件和目录具有不同的复制和纠删码策略。

纠删码策略封装了如何对文件进行编码/解码。

每个策略由以下信息定义:

  1. EC模式:这包括EC组中的数据和奇偶校验块的数量(例如6+3),以及编解码器算法(例如Reed-Solomon,XOR)。
  2. striping cell 的大小:这决定了条纹读写的粒度,包括缓冲区大小和编码工作。

策略被命名为 codec-num data blocks-num parity blocks-cell size 。

目前,支持五种内置策略:RS-3-2-1024k、RS-6-3-1024k、RS-10-4-1024k、RS-LEGACY-6-3-1024k、XOR-2-1-1024k。

默认的复制方案也受支持。它只能设置在目录上,以强制目录采用3倍复制方案,而不是继承其祖先的纠删码策略。此策略使3倍复制方案目录与纠删码目录交织成为可能。

复制总是启用的。在所有EC策略中,默认情况下启用RS(6,3)。

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

目录级EC策略仅影响目录内创建的新文件。创建文件后,可以查询其删除编码策略,但不能更改。

如果删除编码文件重命名为具有不同EC策略的目录,则该文件将保留其现有EC策略。

将文件转换为不同的EC策略需要重写其数据;通过复制文件(例如通过distcp)而不是重命名来做到这一点。

关于 distcp 请参考我的这篇博客——distcp 是什么?如何在两个 HDFS 集群之间传输数据?

我们允许用户通过XML文件定义自己的EC策略,该文件必须包括以下三个部分:

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

一个名为 user_ec_policies.xml.template 的EC策略XML文件示例位于Hadoop conf目录中,用户可以引用。

英特尔 ISA-L

英特尔ISA-L代表英特尔智能存储加速库。

ISA-L是为存储应用程序设计的优化低级函数的开源集合。

它包括为英特尔 AVX 和 AVX2 指令集优化的快速 Reed-Solomon 类型纠删码。

HDFS 纠删码可以利用ISA-L来加速编码和解码计算。

ISA-L支持大多数主要操作系统,包括Linux和Windows。

默认情况下,ISA-L不启用。

上一篇 下一篇