HDFS DataNode Scanners and Disk Checker Explained

众所周知,HDFS中的数据存储在datanode中,HDFS可以通过将相同的数据复制到多个datanode来容忍datanode节点故障。但是,如果一些datanode的磁盘出现故障,会发生什么呢?本博客文章解释了datanode的一些后台工作,以帮助HDFS跨多个datanode管理其数据,以实现容错。特别地,我们将解释块扫描器、卷扫描器、目录扫描器和磁盘检查器:它们做什么、如何工作以及一些相关的配置。

背景:HDFS中的块

为了确保每个人都在同一页上,让我们花点时间来了解一些HDFS的基本原理。我们将特别关注datanode,因为这是本文中描述的大部分内容所在。

正如在HDFS体系结构中描述的,NameNode存储元数据,而datanode存储实际的数据内容。每个DataNode都是一台计算机,通常由多个磁盘(在HDFS术语中是卷)组成。HDFS中的文件包含一个或多个块。根据配置的复制因子,一个块具有一个或多个副本(称为副本)。一个副本存储在一个DataNode的卷上,相同块的不同副本存储在不同的DataNode上。块的详细状态通过块报告从每个DataNode发送到NameNode。正如在理解HDFS恢复过程中所描述的,一个块有几个状态。最终,一个块被定稿并作为块文件和本地文件系统上的元文件存储在DataNode磁盘上。块文件存储文件数据,而元文件存储文件数据的校验和,可用来验证块文件的完整性。元文件是以块文件命名的,另外还包含生成戳。

存储在DataNode磁盘上的块文件及其.meta文件示例:

blog

HDFS的一个核心假设是,硬件故障是常态,而不是例外。当磁盘发生故障时,块文件和元文件中的一个或两个都可能损坏。HDFS具有识别和处理这些问题的机制。但是这些机制是什么呢?具体地说:
datanode节点何时以及如何验证块文件?

Datanode节点如何验证其关于块的内存元数据是否与磁盘上的实际元数据一致?

如果在块读取操作期间发生故障,是由于磁盘错误吗?或者只是一些间歇性错误(例如网络超时)?

这些问题的答案存在于各种DataNode后台任务中,我们将在接下来的小节中讨论它们。介绍了DataNode上的三种类型的任务,每种任务都试图相应地解决上面的一个问题:块扫描器和卷扫描器、目录扫描器和磁盘检查器

 

块扫描器和卷扫描器(Block Scanner & Volume Scanner)

       块扫描器的功能是扫描块数据以检测可能的损坏。由于数据损坏可能随时发生在任何DataNode上的任何块上,因此及时识别这些错误非常重要。通过这种方式,NameNode可以删除损坏的块并相应地重新复制,以维护数据完整性并减少客户机错误。另一方面,我们不想使用太多的资源,这样磁盘I/O仍然可以满足实际的请求。
       因此,块扫描器需要确保可疑块的扫描速度相对较快,而其他块每隔一段时间扫描一次,扫描频率相对较低,没有显著的I/O使用。块扫描器与datanode节点相关联,并包含一组卷扫描器。每个卷扫描器运行自己的线程,并负责扫描DataNode的单个卷。卷扫描器缓慢地逐个读取所有块,并验证每个块。我们称之为常规扫描。注意,这很慢,因为需要读取整个块来执行检查,这会消耗大量I/O。

       卷扫描器还维护一个可疑块列表。这些块导致从磁盘读取异常时抛出特定类型的异常(下面将详细描述)。在扫描期间,可疑块优先于常规块。此外,每个卷扫描器跟踪它在过去10分钟内扫描过的可疑块,以避免重复扫描相同的可疑块。

注意,块扫描器和卷扫描器是实现细节,它们一起处理块扫描的工作。因此,为了简化这篇博客文章,我们将在这篇博客文章的其余部分中同时将块扫描器和卷扫描器称为“块扫描器”。
block scanner用来决定扫描哪个block的机制如下:
A.当一个DataNode服务于来自客户机或另一个DataNode的I/O请求时,如果捕获了IOException,而不是由于网络原因(即套接字超时、管道中断或连接重置),那么该块将被标记为可疑的,并添加到块扫描器的可疑块列表中。

B.块扫描器循环遍历所有块。在每个迭代中,它检查一个块。

   b.1:如果可疑块列表不是空的,它将弹出一个可疑块进行扫描。

   b.2:否则,将扫描普通块。

只有本地(非网络)ioexception才会导致一个块被标记为可疑的,因为我们希望将可疑块列表保持简短并减少误报。这样,损坏就会得到优先处理,并得到及时的报告。

为了跟踪块之间的扫描位置,为每个卷维护一个块游标。游标定期保存到磁盘上(可以通过dfs.block.scanner.cursor.save.interval.ms配置interval,默认值为10分钟)。这样,即使DataNode进程重新启动或服务器重新启动,扫描也不必从头开始。

Block Cursor

正如本节开头所提到的,扫描器的另一个关注点是I/O消耗。无论被扫描的块是可疑的块还是正常的块,我们都不能连续地循环扫描它们,因为这会创建繁忙的I/Os并损害正常的I/O性能。相反,扫描器以配置好的速率运行,以达到节流的目的,在两个扫描周期之间有适当的睡眠间隔。扫描周期是应该执行整个扫描的间隔。当一个块被标记为可疑时,如果它正在等待下一个扫描周期,卷扫描器就会被唤醒。如果在扫描期间没有完成完整的扫描,则扫描将在不睡觉的情况下继续。


重要的配置:
在hdfs-site.xml中,以下两种配置是用于块扫描器的最常用配置。
dfs.block.scanner.volume.bytes.per。其次,将扫描带宽限制为每秒可配置字节。默认值为1M。将此设置为0将禁用块扫描器。dfs.datanode.scan.period。配置扫描周期的时间,这定义了整个扫描执行的频率。由于上面所述的原因,应该将此设置为足够长的时间间隔,以便真正生效。默认值为3周(504小时)。将其设置为0将使用默认值。将此设置为负值将禁用块扫描程序。通过在hdfs-site.xml的DataNode高级配置片段(安全阀)中设置名称/值对,可以通过Cloudera Manager为所有datanode节点设置这些配置:

Cloudera Manager DataNode Configuration

Notable JIRAs:

HDFS-7430 enhances the block scanner to use O(1) memory and enables each volume scanner to run on a separate thread.

HDFS-7686 allows fast rescan of suspicious blocks.

HDFS-10512 fixes an important bug that a race condition could terminate the volume scanner.

目录扫描仪(DirectoryScanner)

当块扫描器确保存储在磁盘上的块文件处于良好状态时,datanode将块信息缓存到内存中。确保缓存的信息准确是至关重要的。目录扫描器检查并修复缓存和磁盘上实际文件之间的不一致。目录扫描器定期扫描数据目录中的块和元数据文件,并协调磁盘中维护的块信息和内存中的块信息之间的差异。
检查所有差异的逻辑: 只检finalized 状态的块。

如果一个块被标记为损坏,它将通过下一个块报告报告给NameNode。然后,NameNode将从来自好的副本的节点复制块数据。
与块扫描器类似,目录扫描器也需要节流。节流是通过将每个目录扫描线程限制为每秒只运行给定数量的毫秒来完成的。
重要的配置:
dfs.datanode.directoryscan.throttle.limit.ms.per。sec控制一个线程每秒应该运行多少毫秒。注意,这个限制是针对每个线程的,而不是针对所有线程的聚合值。默认值为1000,这意味着节流被禁用。只有1到1000之间的值才是有效的。设置无效值将导致油门被禁用,并记录一条错误消息。

dfs.datanode.directoryscan。线程控制目录扫描器可以并行拥有的最大线程数。默认值为1。

interval控制目录扫描线程运行的时间间隔(以秒为单位)。将此设置为负值将禁用目录扫描程序。默认值为6小时(21600秒)。

上述配置可以在每个DataNode上的hdfs-site.xml中更改,以生效。默认值在大多数情况下应该是足够的,表示集群I/O和及时纠正数据损坏之间的良好平衡。通过将名称/值对添加到hdfs-site.xml的DataNode高级配置片段(安全阀),还可以通过Cloudera Manager方便地设置这些值:

Cloudera Manager DataNode Configuration

Notable JIRAs:

HDFS-8873  Allows the directoryScanner to be rate-limited

磁盘检查程序(DiskChecker)

除了上面提到的扫描器,datanode还可以在后台线程中运行磁盘检查器,以确定一个卷是否不健康,以及是否要删除它。使用磁盘检查器的原因是:如果在卷级别出现错误,HDFS应该检测到错误,并停止尝试写入该卷。另一方面,删除一个卷并不简单,而且影响很大,因为它将使该卷上的所有块都不可访问,而且HDFS必须处理由于删除而导致的所有复制不足的块。因此,磁盘检查器执行最基本的检查,使用非常保守的逻辑来考虑故障。
检查中的逻辑非常简单——它按顺序检查DataNode上的以下目录:
目录“finalized”

目录“tmp”

目录“rbw”


当检查这3个目录时,磁盘检查器会检查:(finalizedDir: 递归遍历目录树,检查所有子目录)
1. 目录及其所有父目录都存在,或者可以创建其他目录。

2. 路径确实是目录类型。

3. 进程对目录具有读、写和执行权限。

严格地说,我们应该递归地对这三个目录下的所有子目录进行相同的检查。但是这样做会产生过多的I/Os,没有什么好处——不管怎样,那些错误的块将被添加到块扫描器中的可疑块中,因此它们将很快被扫描/报告。另一方面,像HBase这样的应用程序对性能非常敏感,并努力确保sla,这里过多的I/Os可能会造成峰值,这是不能容忍的。因此,只执行上面列出的3个检查。


当块扫描器和目录扫描器在DataNode启动时被激活并定期扫描时,磁盘检查器只按需运行,而磁盘检查器线程是惰性创建的。具体地说,磁盘检查器只在常规I/O操作(例如关闭块或元数据文件、目录扫描器报告错误等)期间捕捉到DataNode上的IOException时才运行。此外,磁盘检查器在5~6秒内最多只能运行一次。在创建磁盘检查器线程时,将随机生成此特定周期。

此外,如果启动时失败卷的数量大于配置的阈值,则DataNode将自动关闭。DataNode在尝试将所有配置的存储位置都投入使用后,通过比较所有配置的存储位置和实际使用的存储位置之间的差异来执行这个初始检查。该阈值可以通过dfs.datanode. failure .vol . tolerance在hdfs-site.xml中配置。默认值为0。
Cloudera Manager在DataNode下显式列出了这个配置项,称为“允许DataNode失败的卷”:

Cloudera Manager DataNode configurator

Notable JIRAs:

HDFS-7722 DataNode#checkDiskError should also remove Storage when error is found.

HDFS-8617 Throttle DiskChecker#checkDirs() speed.

HADOOP-13738 DiskChecker should perform some disk IO

结论

datanode节点中的各种后台任务使HDFS数据持久可靠。应该仔细地对它们进行调优,以维护集群的健康状态并减少I/O的使用。本博客解释了以下背景任务:块扫描程序、卷扫描程序、目录扫描程序和磁盘检查程序、它们的功能、工作原理以及一些相关配置。

在每个DataNode上都难以记住和配置本文中描述的所有配置吗?没问题!Cloudera Manager使这一功能变得方便和易于管理——可以在一个地方配置它们,并推送到所有的datanode。

 

原文地址:https://blog.cloudera.com/blog/2016/12/hdfs-datanode-scanners-and-disk-checker-explained/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值