学习大数据技术,就不可能避开hadoop,因为hadoop框架是分布式系统的基础。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,而MapReduce则为海量的数据提供了计算。
这篇博文将以paper:The Hadoop Distributed File System,为学习素材,对HDFS的基础知识及框架进行梳理。
HDFS是一个主/从( master/slave )体系结构。一个HDFS集群由一个单一的NameNode,主服务器管理文件系统命名并控制客户端对文件的访问。此外,有许多的datanode,通常一个集群中的每个节点,管理存储在节点上运行。HDFS公开文件系统命名空间和允许将用户数据存储在文件中。在内部,一个文件被分成一个或多个块,这些块存储在一组datanode。NameNode执行文件系统命名空间操作,如打开,关闭,重命名文件和目录。它还决定了映射datanode的 blocks。datanode负责从文件系统的读写请求服务客户。还datanode执行块创建、删除和复制指令从NameNode。
namenode和datanode是设计用于在商用机器上运行的软件。这些机器通常运行GNU/Linux操作系统(OS)。使用Java语言构建HDFS;支持Java的任何机器都可以运行NAMENODE或DATEAON软件。使用高度可移植的Java语言意味着HDFS可以部署在各种各样的机器上。典型的部署有一台专用的机器,它只运行namenode软件。集群中的其他每台机器都运行一个datanode软件实例。该体系结构并不排除在同一台机器上运行多个datanode,而是在实际部署中运行,这种情况很少发生。
集群中单个nameNode的存在极大地简化了系统的体系结构。NameNode是所有HDFS元数据的仲裁器和存储库。系统的设计方式是,用户数据永远不会通过NameNode。
具体如下图所示:
从图中可以清晰看到整个框架的关系:Namenode是一个管理metadata并于datanode通信,但是它不存储data。datanode是存储数据block的地方;Client用户,要和nameNode通信,读数据是对datanode进行操作。
HDFS支持传统的分层文件组织。用户或应用程序可以创建目录并将文件存储在这些目录中。文件系统命名空间层次结构与大多数其他现有文件系统类似;可以创建和删除文件、将文件从一个目录移动到另一个目录或重命名文件。HDFS支持用户配额和访问权限。HDFS不支持硬链接或软链接。然而,HDFS体系结构并不排除实现这些特性。
nameNode维护文件系统namespace。对文件系统命名空间或其属性的任何更改都由namenode记录。应用程序可以指定HDFS应该维护的文件副本的数量。文件的副本数称为该文件的复制因子。此信息由nameNode存储。
下面开始介绍一下每个部分的细节:
HDFS命名空间是文件和目录的层次结构。文件和目录在NameNode上由inode表示,它记录诸如权限、修改和访问时间、命名空间和磁盘空间配额等属性。文件内容被分割成大的数据块(通常为128M,但用户可以选择文件,一个文件一个文件),文件的每个块在多个DataNode(通常为三个,但用户可以选择文件一个文件)独立复制。NameNode维护命名空间树,并将文件块映射到DataNode(文件数据的物理位置)。想要读取文件的HDFS客户机首先与NameNode联系以获取包含该文件的数据块的位置,然后从离客户机最近的DateNode读取块内容。在写入数据时,clien请求NameNode指定一组三个DateNode来承载数据块及副本。然后,client以管道方式(pipeline)将数据写入DataNode。当前设计为每个集群都有一个NameNode。每个集群可以有数千个DataNode和数万个HDFS的client,因为每个DataNode可以同时执行多个应用程序任务。
HDFS将整个命名空间保存在RAM中。把inode数据和包含每个文件的数据块组成的列表文件两个组成的名称系统叫做image。被持久化存储在本地机器的原生文件系统中的image称为checkpoint。NameNode还将image的修改日志命名为journal,同时也存储在本地机器的原生文件系统中。为了提高耐久性,可以在其他服务器上复制checkpoint和journal的冗余副本(备份使用)。在重新启动期间,NameNode通过读取命名空间和重放日志来还原(replay)命名空间。块副本的位置可能会随着时间而改变,并且不是持久性checkpoint的一部分。
DateNode上的每个数据块的副本由本地主机的本机文件系统中的两个文件表示。第一个文件包含数据本身,第二个文件是块的元数据,包括块数据的校验和(checksums)和块的生成戳(generation stamp)。数据文件的大小等于块的实际长度,不需要额外的空间来将其四舍五入到与传统文件系统相同的标称块大小。因此,如果一个块是半满的,它只需要本地驱动器上整个块的一半空间。
在启动期间,每个DateNode连接到NameNode并执行握手(handshake)。握手的目的是验证命名空间(namespace)ID和DateNode的软件版本。如果其中一个与NameNode不匹配,则DateNode将自动关闭。
格式化文件系统实例时,会将命名空间ID分配给该实例。命名空间ID持久存储在集群的所有节点上。具有不同命名空间ID的节点将无法加入集群,从而保留文件系统的完整性。
软件版本的一致性很重要,因为不兼容的版本可能会导致数据损坏或丢失(corruption or loss),并且在数千台计算机的大型集群上,很容易忽略在软件升级之前未正确关闭或升级期间不可用的节点。
允许新初始化且没有任何命名空间ID的DataNode加入群集并接收群集的命名空间ID。
握手之后,DateNode向NameNode注册。DateNode持续存储其唯一的存储ID。存储ID是DateNode的内部标识符,即使重新启动时使用不同的IP地址或端口,也可以识别它。当存储ID第一次注册到namenode时,它将被分配给datanode,之后再也不会更改.
DateNode通过发送块报告来识别其所拥有的块副本。块报告包含块ID、生成戳和服务器主机的每个块副本的长度。第一个块报告在DateNode注册后立即发送。随后的块报告每小时发送一次,并向namenode提供块副本在集群中的最新视图(up-to-date view)。
在正常操作期间,DateNode向NameNode发送心跳信号(heartbeats),以确认DateNode正在运行,并且它承载的块副本可用。默认心跳间隔为3秒。如果NameNode在十分钟内没有收到来自DateNode的心跳,则NameNode会认为该DateNode已停止服务,并且该DateNode承载的块副本不可用。然后,namenode安排在其他datanode上创建这些块的新副本。
datanode的心跳还包含有关总存储容量、使用中的存储部分以及当前正在进行的数据传输数量的信息。这些统计信息用于namenode的空间分配和负载平衡决策。
namenode不直接调用datanodes。它使用对心跳的回复来向DateNode发送指令。指令包括以下命令:
1.将块复制到其他节点;
2.删除本地块副本;
3.重新注册或关闭节点;
4.立即发送区块报告。
这些命令对于维护整个系统的完整性很重要,因此即使在大型集群中,也必须保持心跳频率。namenode每秒可以处理数千次心跳,而不会影响其他namenode操作。
用户应用程序(user application)使用HDFS Client访问文件系统,该Client是一个代码库,用于导出HDFS文件系统的界面。
与大多数传统的文件系统类似,HDFS支持读取、写入和删除文件的操作,以及创建和删除目录的操作。用户通过命名空间中的路径引用文件和目录。用户应用程序通常不需要知道文件系统元数据和存储在不同的服务器上,或者块具有多少个副本。
当应用程序读取文件时,HDFS Client首先向namenode请求承载文件块副本的DateNode列表。然后它直接联系一个DateNode并请求所需块的传输。当Client写入时,它首先要求namenode选择datanodes来承载文件第一个块的副本(replicas)。Client组织一个从节点到节点的管道,并发送数据。当第一个块被填满时,客户机请求选择新的DateNode来承载下一个块的副本。一个新的管道被组织起来,Client发送文件的更多字节。每个DateNode的选择都可能不同。Client、NameNode和DateNode之间的交互如图1所示。与传统的文件系统不同,HDFS提供了一个API,用于公开文件块的位置。这允许类似mapreduce框架的应用程序将任务调度到数据所在的位置,从而提高读取性能。它还允许应用程序设置文件的复制因子。默认情况下,文件的复制系数为3。对于经常访问的关键文件或文件,具有更高的复制因子可以提高它们对错误的容忍度并增加它们的读取带宽。
HDFS Client通过向NameNode提供路径来创建新文件。对于文件的每个块,namenode返回一个DataNode列表,以承载其副本。然后,Client将数据传输到所选的DataNode,这些节点最终确认了块副本的创建过程。(流程图如上图)
命名空间image是文件系统的元数据,其将应用程序数据组织定义为目录和文件。写入磁盘的image的持久化记录称为checkpoint。Journal是用于对文件系统所做更改的预写提交日志,这些更改必须是持久的存储。对于每个client启动的事务,更改都记录在Journal中,并且在将更改提交到HDFS client之前,将刷新并同步日志文件。checkpoint文件永远不会被NameNode更改;当重新启动期间,创建新的checkpoint、管理员重新请求时或下一节中定义的checkpoint时,该文件将全部被替换(被新的checkpoint替换)。在启动期间,namenode从checkpoint初始化命名空间image,然后从Journal中重新更改,直到image与文件系统的最后一个状态保持最新。在namenode开始为client提供服务之前,新的checkpoint和空Journal将被写回存储目录。
如果checkpoint或Journal丢失或损坏,则命名空间信息将部分或全部丢失。为了保留这些关键信息,可以将HDFS配置为将checkpoint和journal存储在多个存储目录中。建议的做法是将目录放在不同的卷上(volumes),并将一个存储目录放在远程NFS服务器上。第一个选项可防止单卷故障造成的损失,第二个选项可防止整个节点发生故障。如果nameNode在将Journal写入某个存储目录时出错,它会自动将该目录从存储目录列表中排除。如果没有可用的存储目录,NameNode将自动关闭。
namenode是一个多线程系统,同时处理来自多个client的请求。将事务(transaction)保存到磁盘将成为瓶颈,因为所有其他线程都需要等待其中一个线程初始化的同步刷新和同步过程完成。为了优化这个过程,namenode批处理由不同client启动的多个事务。当namenode的一个线程启动刷新和同步操作时,此时批处理的所有事务都将一起提交。其余的线程只需要检查它们的事务是否已保存,而不需要启动刷新和同步操作。
hdfs中的namenode除了提供client请求的主要角色外,还可以执行其他两个角色中的任何一个,CheckpointNode或BackupNode。角色(role)是在节点启动时指定的。
CheckpointNode定期组合现有的checkpoint和journal,以创建新的checkpoint和空journal。CheckpointNode通常运行在与nameNode不同的主机上,因为它与nameNode具有相同的内存需求。它从namenode下载当前的checkpoint和journal文件,将它们进行本地合并,并将新的checkpoint返回到namenode。创建定期checkpoint是保护文件系统元数据(metadata)的一种方法。如果命名空间image或journal的所有其他持久副本都不可用,则系统可以从最新的checkpoint启动。
创建一个checkpoint可以让namenode在新checkpoint上载到namenode时截断日志的尾部 (Creating a checkpoint lets the NameNode truncate the tail of the journal when the new checkpoint is uploaded to the NameNode)。HDFS集群可以长时间运行,而不需要重新启动,在此期间Journal会不断增长。如果Journal增长非常大,jouranl文件丢失或损坏的概率就会增加。此外,一个非常大的jouranl往往需要重新启动nameNode的时间。对于大型集群,处理一周的日志需要一个小时。好的做法是创建一个每日checkpoint。
最近引入的HDFS特性是backupnode。与CheckpointNode一样,backupnode能够创建定期checkpoint,但是它还维护文件系统命名空间的内存中最新image,该image始终与nameNode的状态同步。
backupnode接受来自活动nameNode的命名空间事务的日志流,将它们保存到自己的存储目录,并将这些事务应用到内存中自己的命名空间image。namenode将backupnode视为日志存储,与在其存储目录中处理日志文件相同。如果namenode失败,则backupnode在内存中的image和磁盘上的checkpoint是最新命名空间状态的记录。
backupnode可以创建一个checkpoint,而不需要从活动的namenode下载checkpoint和日志文件,因为它的内存中已经有了最新的命名空间消息。这使得backupnode上的checkpoint进程更高效,因为它只需要将命名空间保存到本地存储目录中。
backupnode可以被视为只读的namenode。它包含除块位置之外的所有文件系统元数据信息。它可以执行常规nameNode的所有操作,这些操作不涉及修改命名空间或块位置知识。使用backupnode提供了在不使用持久存储的情况下运行namenode的选项,并将命名空间状态的责任委托给backupnode。
在软件升级过程中,由于软件缺陷或人为错误而损坏系统的可能性增加。在HDFS中创建快照(snapshots)的目的是将升级期间存储在系统中的数据的潜在损坏降至最低。
快照机制允许管理员持续保存文件系统的当前状态,这样,如果升级导致数据丢失或损坏,则可以回滚升级并将HDFS返回到快照时的命名空间和存储状态。
每当系统启动时,都会在集群管理员的选项中创建快照(只能存在一个)。如果请求快照,则namenode首先读取checkpoint和journal文件,并将它们合并到内存中。然后它将新的checkpoint和空journal写入新的位置,以便旧的checkpoint和journal保持不变。
在握手(handshake)过程中,namenode指示datanodes是否创建本地快照。无法通过复制数据文件目录来创建dataNode上的本地快照,因为这将需要将群集上每个dataNode的存储容量翻倍。相反,每个dataNode创建一个存储目录的副本,并将现有的块文件硬链接到其中。当datanode删除一个块时,它只删除硬链接,并在附加期间使用copy-on-write技术进行块修改。因此,旧的块副本在旧目录中保持不变。
重新启动系统时,群集管理员可以选择将HDFS回滚到快照状态。nameNode恢复创建快照时保存的checkpoint。datanodes恢复以前重命名的目录并初始化后台进程,以删除在创建快照后创建的块副本。既然选择了向后滚动,就没有向前滚动的规定。集群管理员可以通过命令系统放弃快照来恢复快照占用的存储,从而使软件升级。系统的发展可能导致nameNode的checkpoint和journal文件的格式发生更改,或者dataNode上的块副本文件的数据报告发生更改。布局版本标识数据表示格式,并存储在nameNode和dataNode的存储目录中。在启动过程中,每个节点将当前软件的布局版本与存储在其存储目录中的版本进行比较,并自动将数据从旧版本转换为新版本。当系统以新软件布局版本重新启动时,转换需要强制创建快照。
HDFS不分离nameNode和dataNode的布局版本,因为快照创建必须是一个全集群工作,而不是节点选择事件。如果由于软件错误而升级的nameNode清除了其image,那么仅备份命名空间状态仍然会导致数据完全丢失,因为nameNode将无法识别dataNode报告的块,并将命令删除这些块。在这种情况下,回滚将恢复元数据,但数据本身将丢失。为了避免灾难性的破坏,需要一个协调的快照。
一个应用程序通过创建一个新文件并将数据写到HDFS中来添加数据。关闭文件后,不能更改或删除写入的字节,除非可以通过重新打开文件进行追加来将新数据添加到文件中。HDFS实现了一个单一的编写器、多个读卡器模型。
打开要写入的文件的HDFS客户机被授予该文件的租约;其他客户机不能写入该文件。写入客户机通过向nameNode发送心跳(heartbeat)来定期更新租约。文件关闭时,租约将被吊销。租赁期限受软限制和硬限制的约束。在软限制到期之前,写入程序必须对文件进行独占访问。如果软限制到期,并且客户端无法关闭文件或续订租约,则另一个客户端可以抢占租约。如果在硬限制到期(一小时)后,客户端未能续订租约,HDFS假定客户端已退出,并将代表编写器自动关闭文件,然后恢复租约。写入者的租约不会阻止其他客户机读取该文件;一个文件可能有许多并发的读卡器。
HDFS文件由块组成。当需要一个新块时,namenode会分配一个具有唯一块ID的块,并确定一个dataNode列表来承载该块的副本。dataNode形成一个管道,其顺序将从客户端到最后一个dataNode的总网络距离最小化。字节作为一系列数据包被推送到管道中。应用程序在客户端写入第一个缓冲区的字节。在一个包缓冲区被填满(通常是64KB)之后,数据被推送到管道中。下一个数据包可以在接收到前一个数据包的确认之前推送到管道。未完成数据包的数量受客户端“未完成数据包”窗口大小的限制。
将数据写入HDFS文件后,HDFS不保证在关闭文件之前数据对新的读卡器是可见的。如果用户应用程序需要可见性保证,它可以显式调用hflush操作。然后立即将当前数据包推送到管道中,hflush操作将等待管道中的所有dataNode了解数据包的成功传输。在hflush操作之前写入的所有数据一定对读者可见。
如果没有出现错误,块构造过程将经历上图所示的三个阶段,其中显示了由三个DataNode(DN)组成的管道和由五个数据包组成的块。如图所示,粗线表示数据包,虚线表示已知消息,细线表示设置和关闭管道的控制消息。垂直线表示客户机和三个dataNode上的活动,时间从上到下进行。从T0到T1是管道设置阶段。间隔T1到T2是数据流阶段,其中T1是发送第一个数据包的时间,T2是接收最后一个数据包的确认的时间。在这里,hflush操作发送第二个数据包。hFlush指示随包数据一起传输,不是单独的操作。最后一段t2至t3是该区块的管道关闭阶段。
在由数千个节点组成的集群中,节点的故障(最常见的存储故障)每天都会发生。存储在dataNode上的副本可能由于内存、磁盘或网络故障而损坏。HDFS为HDFS文件的每个数据块生成并存储校验和(checksum)。读取时,HDFS客户机会验证校验和,以帮助检测由客户机、dataNode或网络引起的任何损坏。当客户机创建HDFS文件时,它为每个块计算校验和序列,并将其与数据一起发送到dataNode。dataNode将校验和存储在与块的数据文件分开的元数据文件中。当hdfs读取一个文件时,每个块的数据和校验和都被发送到客户机。客户端为接收的数据计算校验和,并验证新计算的校验和是否与接收的校验和匹配。如果没有,客户机会通知nameNode损坏的副本,然后从另一个dataNode获取该块的其他副本。
当客户机打开要读取的文件时,它从nameNode获取块列表和每个块副本的位置。每个块的位置按它们与读卡器的距离排序。读取块的内容时,客户机首先尝试最接近的副本。如果读取尝试失败,客户端将依次尝试下一个副本。如果目标dataNode不可用、节点不再承载块的副本或在测试校验和时发现副本已损坏,则读取可能会失败。
HDFS允许客户机读取打开以进行写入的文件。当读取打开进行写入的文件时,nameNode不知道最后一个仍在写入的块的长度。在这种情况下,在开始读取内容之前,客户机要求其中一个副本提供最新的长度。
HDFS I/O的设计特别针对批处理系统(如MapReduce)进行了优化,因为它需要高吞吐量来进行顺序读写。然而,为了支持向HDF提供实时数据流的scribe或提供对大型表的随机实时访问的HBase等应用程序,许多人都在努力改进其读/写响应时间。
对于大型集群,在平面拓扑中连接所有节点可能并不实际。一种常见的做法是将节点分布在多个机架上。机架的节点共享一个交换机,机架交换机由一个或多个核心交换机连接。不同机架中的两个节点之间的通信必须经过多个交换机。同一机架中节点之间的带宽大于不同机架中节点之间的网络带宽。下图描述了一个具有两个机架的集群,每个机架包含三个节点。
HDFS根据两个节点之间的距离估计网络带宽。节点到其父节点的距离假定为一。两个节点之间的距离可以通过求和到最近的共同祖先的距离来计算。两个节点之间的距离越短,意味着它们可以用来传输数据的带宽越大。
HDFS允许管理员配置一个脚本,在给定节点地址的情况下重新转换节点的机架标识。NameNode是解析每个dataNode的机架位置的中心位置。当一个dataNode向nameNode注册时,nameNode运行一个配置好的脚本来决定该节点属于哪个机架。如果没有配置这样的脚本,则namenode假定所有节点都属于默认的单个机架。
副本的放置对于HDFS的数据可靠性和读/写性能至关重要。一个好的副本放置策略应该可以提高数据的可靠性、可用性和网络带宽利用率。目前,HDFS提供了一个可配置的块放置策略接口,这样用户和研究人员就可以试验和测试任何最适合其应用程序的策略。
默认的HDFS块放置策略在最小化写入成本和最大化数据可靠性、可用性和聚合读取带宽之间提供了一个折衷方案。创建新块时,HDFS将第一个副本放在编写器所在的节点上,将第二个和第三个副本放在不同机架中的两个不同节点上,其余副本放在随机节点上,限制条件是一个节点上放置的副本不超过一个,同一机架中放置的副本不超过两个。n副本数量少于机架数量的两倍。选择将第二个和第三个副本放在不同的机架上,可以更好地在集群中为单个文件分发块副本。如果前两个repli-cas放在同一个机架上,对于任何文件,其块副本的三分之二将放在同一个机架上。
选择所有目标节点后,节点将按其接近第一个副本的顺序组织为管道。数据按此顺序推送到节点。对于读取,nameNode首先检查客户机的主机是否位于集群中。如果是,块位置将按与读卡器的接近顺序返回给客户机。按此首选顺序从dataNode读取块。(MapReduce应用程序通常在群集节点上运行,但只要主机可以连接到NameNode和dataNode,它就可以执行HDFS客户机。)
该策略减少了机架间和节点间的写入流量,并通常提高了写入性能。由于机架故障的概率远小于节点故障的概率,因此此策略不会影响数据可靠性和可用性保证。在通常的三个副本的情况下,它可以减少读取数据时使用的聚合网络带宽,因为一个块只放置在两个唯一的机架上,而不是三个机架上。
默认的HDFS副本放置策略可以总结如下:
1.任何dataNode都不包含任何块的多个副本。
2.如果集群上有足够的机架,则没有机架包含同一块的两个以上副本。
namenode努力确保每个块始终具有预期数量的副本。当来自dataNode的块报告到达时,namenode检测到块已被欠复制或过度复制。当块被过度复制时,nameNode选择要删除的副本。namenode不希望减少承载副本的机架的数量,第二个选择是使用最少的可用磁盘空间从datanode中删除副本。目标是在不降低数据块可用性的情况下平衡跨dataNode的存储利用率。
当一个块被复制时,它将被放入复制优先级队列。只有一个副本的块具有最高优先级,而具有超过其复制因子三分之二的副本数的块具有最低优先级。后台线程定期扫描复制队列的头部,以决定将新副本放在何处。块复制遵循与新块放置相似的策略。如果现有副本的数量为1,HDFS会将下一个副本放在不同的机架上。如果块有两个现有副本,如果两个现有副本位于同一机架上,则第三个副本将放置在不同的机架上;另一方面,第三个副本将放置在与现有副本位于同一机架上的不同节点上。这里的目标是降低创建新副本的成本。
nameNode还确保块的所有副本并非都位于一个机架上。如果namenode检测到一个块的副本在一个机架上结束,namenode会将该块视为未复制的,并使用上述相同的块放置策略将该块复制到不同的机架上。在namenode收到创建副本的通知后,块将被过度复制。然后,namenode将决定删除旧的复制副本,因为过度复制策略不希望减少机架的数量。
副本放置的示意图如下图所示:
HDFS块放置策略不考虑dataNode磁盘空间利用率。这是为了避免将新的更可能被引用的数据放在dataNode的一个子集上。因此,数据可能并不总是均匀地跨数据节点放置。当新节点添加到集群中时,也会出现不平衡。
Balancer是一个平衡HDFS集群上磁盘空间使用的工具。它以一个阈值作为输入参数,它是(0,1)范围内的一个分数(fraction)。如果对于每个dataNode,节点的利用率(节点的已用空间占节点总容量的比率)与整个集群的利用率(集群中已用空间占集群总容量的比率)相差不超过阈值,则集群是平衡的。
该工具被部署为可由集群管理员运行的应用程序。它迭代地将副本从利用率较高的dataNode移动到利用率较低的dataNode。平衡器的一个关键要求是保持数据可用性。当选择要移动的复制副本并确定其目标时,平衡器保证该决定不会减少复制副本的数量或机架的数量。
平衡机通过最小化机架间数据复制来优化平衡过程。如果均衡器决定将一个副本A移动到另一个机架上,而目标机架恰好有一个相同块的副本B,则数据将从副本B而不是副本A复制。
第二个配置参数限制重新平衡操作所消耗的带宽。允许的带宽越高,集群达到平衡状态的速度越快,但与应用程序进程的竞争越激烈。
每个dataNode运行一个块扫描程序,定期扫描其块副本,并验证存储的校验和是否与块数据匹配。在每个扫描周期中,块扫描程序调整读取带宽,以便在可配置周期内完成验证。如果客户机读取完整的块并校验和验证成功,它将通知dataNode。dataNode将其视为对复制副本的验证。
每个块的验证时间存储在一个可读的日志文件中。在任何时候,顶级datanode目录中最多有两个文件,即current和prevlogs。新的验证时间将附加到当前文件中。相应地,每个dataNode都有一个按副本的验证时间排序的内存中扫描列表。
每当读客户机或块扫描程序检测到损坏的块时,它就会通知nameNode。nameNode将副本标记为已损坏,但不会立即计划删除副本。相反,它开始复制块的良好副本。只有当好的副本计数达到块的复制因子时,才计划重新移动损坏的副本。该政策旨在尽可能长时间地保存数据。因此,即使块的所有副本都已损坏,策略也允许用户从损坏的副本中检索其数据。
集群管理员通过列出允许的节点的主机地址来指定哪些节点可以加入集群。注册和不允许注册的节点的主机地址。管理员可以命令系统重新评估这些包含和排除列表。将被排除的群集中的当前成员标记为要解除授权。一旦一个dataNode被标记为解除授权,它将不会被选中作为复制副本放置的目标,但它将继续服务于读取请求。nameNode开始计划将其块复制到其他dataNode。一旦namenode检测到解除授权dataNode上的所有块都被复制,该节点就会进入解除授权状态。然后可以安全地从集群中删除它,而不会危及任何数据可用性。
在处理大型数据集时,将数据复制到HDFS集群中或从HDFS集群中复制数据是非常困难的。HDFS提供了一个名为distcp的工具,用于大型集群间/集群内并行复制。它是一个mapreduce作业;每个map任务都将源数据的一部分复制到目标文件系统中。MapReduce框架自动处理并行任务调度、错误检测和恢复。
以上内容是来自于HDFS发表的论文,完全可以对HDFS的这个核心里面有一个整体和细微的了解。
盗一张图做最后的总结:
HDFS就一个利用多个廉价机器构成的一个分布式文件系统,nameNode是其中一台机器,是一个管理者,其他机器中每一台机器就是一个dataNode,dataNode上存储数据块,一个文件有被分了多少块,每一块在那个机器上,只有nameNode知道,都存储在了元数据中。client就是用户,如果希望对数据读写,就需要先和管理者NameNode沟通,获得对应的元数据信息,然后在分别于对应的dataNode联系,进行操作。那么整个系统之间的稳定维护需要周期性检测心跳,确保哪些机器还活着等一系列操作,这也保证了系统的稳定和可靠,具有高容错能力。
因为这是原版论文的内容,但是目前已经过了很多年,所以HDFS也有了很多的完善和优化的地方,具体大家可以看看Hadoop的文档。