Hadoop分布式文件系统:结构与设计
Hadoop 分布式文件系统 (HDFS)是一个设计为用在普通硬件设备上的分布式文件系统。它与现有的分布式文件系统有很多近似的地方,但又和这些文件系统有很明显的不同。HDFS 是高容错的,设计为部署在廉价硬件上的。HDFS对应用程序的数据提供高吞吐量,而且适用于那些大数据集应用程序。HDFS开放了一些POSIX的必须接 口,容许流式访问文件系统的数据。HDFS最初是为了Apache 的Nutch网络搜索引擎项目的下层构件而设计的。是Hadoop项目的一部分,而这又是Apache的 Lucene项目的一部分。本项目的地址是:http://projects.apache.org /projects/hadoop.html。
- 硬 件错误是正常的,而不是异常。HDFS实例由成百上千个服务器组成,每个都存储着文件系统的一部分数据。事实上,这就会有大量的组件,而 每个组件出故障的可能性都很大,这意味着HDFS总有一些组件是不能工作的。因此,检测错误并快速自动恢复就成了HDFS的核心设计目标。
- 运 行在HDFS上的应用程序需要流式的访问它们的数据集,它们也不是通常运行在普通文件系统上的普通应用程序。HDFS为了那些批量处理而 设计的,而不是为普通用户的交互使用。强调的是数据访问的高吞吐量而不是数据访问的低反应时间。POSIX强加的很多硬性需求是HDFS上应用程序所不需 要的, 这些POSIX语义在一些关键环境下被用来提高数据的吞吐频率。
- 运行在HDFS上的应用程序 使用大数据集。HDFS一个典型的文件可能是几GB的或者几TB的。因此,HDFS适用于大文件。这将提供高集成带宽,并在一几集群中提供上百个结点。一 个实例可能支持上千万个文件。
HDFS的应用程序需要对文件实行一次性写,多次读的访问模式。文件一 旦建立后写入,文件就不需要再更改了。这样的假定简化了数据一致性问题并使高数据吞吐量成为可能。MapReduce程 序或者网络爬虫程序就很适合使用这样的模型。当然未来计划支持增量写。
如 果就在数据的旁边就执行对这些数据的操作,那么程序所使用的设备就会 很高效。这当文件相当巨大的时候就尤其正确。这可以减少网络的拥塞和提高系统的吞吐量。这个假设还意味着,常常是把计算迁移到数据存储的近处更好,而不是 把数据传输到程序运行的地方。HDFS提供了程序接口以便把他们自己移动到数据存储的地方执行。
- HDFS设计为容易的从一个 平台移动到另一个平台。这有助于HDFS被采用做为一个大程序集合的工作平台。
- HDFS 是主/从结构的。一 个集群有一个名字结点,也就是主控制服务器,负责管理文件系统的名字空间并协调客户对文件的访问。还有一堆数据结点,一般一个物理结点上部署一个,负责它 们所在的物理结点上的存储管理。HDFS开放文件系统的名字空间以便让用户数据存储的文件中。内部,一个文件被分割为一个或者多个数据块,这些数据块存储 在一组数据结点中。名字结点执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录,还决定数据块从数据结点的映射。数据结点负责提供客户的读写 请求。数据结点还依照名字结点的指令执行数据块的创建、删除复制工作。
名字结点和数据结点是设计为运行在普 通机器上的软件组件。这些机器大多运行GNU/Linux操作系统。HDFS使用 JAVA语言来实现;任何支持JAVA的机器都可以运行名字结点和数据结点软件。使用高度可以移植的JAVA语言意味着HDFS可以被很多种机器使用。一 个典型的部署有一台指定的机器只运行名字结点,体系结构并不排除在那台机器上也运行数据结点,但是现实中的部署很少那样使用。
一个集群中只有一个名字结点大大简化了系统机构。名字结点做为所有系统元数据的存储和仲裁者。系统这样设计就会使用户 数据从不会流经名字结点。
HDFS 支持传统的文件组 织体系结构。用户或者程序可以创建目录,并在目录中存储文件。名字空间的结构和大多现有文件系统类似。你可以创建、删除文件,把文件从一个目录移动到另一 个目录,或者重命名文件。HDFS还没有实现用户配额和访问权限控制,也不支持硬连接和软连接。当然体系也不妨碍实现这些特性。
- 名字结点维护系统的名字空间,它将记录名字空间内的任何改动或者名字空间本身的属性改 动。用户可以指定HDFS中文件复制的份数,这个份数称为复制因子,由名字结点记录。
HDFS 被设计为在一个大 集群里跨机器、可靠的存储非常大的文件。每个文件都存储为一系列的块,同一文件中除最后一块以外的所有块都是一样大的。文件的块都通过复制来保证容错。每 个文件的块的大小和复制因子都是可以配置的。程序可以指定文件复制的次数,复制因子可以在文件创建时候指定,也可以在以后指定。HDFS的文件都是一次性 写入的,并且严格限制任何时候都只有一个写用户。
名字结点根据块复制状态做出所 有决定,它会周期的收到来自集群内数据结点的心跳和块报告。能收到心跳证明数据结点工作是正常的。一个块报告应该包括数据结点上所有块的列表。
复 制品的位置对于HDFS的可靠性和性能来说是很关键的,和其他分布式 文件系统最大的区别就是它能优化复制品的位置,这个特性需要大量的调整和经验。小心衡量复制品的放置是为了提高数据的可靠性、可用性、网络带宽利用率。目 前对于复制品放置的策略只是朝这个方向努力的第一步,短期的目标是要在生产系统中验证,更多学习它的行为,并建立一个基础来测试和研究更复杂的策略。
大的HDFS实体在一大堆机器上运行着,这些机器可能要跨几个机柜来放。不同柜子里的两个结点通信的时候要通过交换 机。大多数情况下,同一个机柜的机器间的带宽比不同机柜的机器间的带宽要大。
启 动的时候,每个数据结点确 定自己所在的机柜并通知名字结点注册表中此机柜的ID。HDFS提供一些API,以方便可拆卸模块用来确定自己所在的机柜的ID。 有个简单但不是很理想的策略是:在不同机柜上放置复制品。这防止在整个机柜宕掉的时候丢失数据,还容许在读数据的时候使用多个机柜的带宽。这个策略还可以 均匀的放置复制品,以便在组件失败的时候平衡负载。但是,这个策略会增加写的代价,写操作需要跨机柜的传输数据块。
对于 一般的情况,当复制因子是3的时候,HDFS的部署策略是:在本地机柜放置一个结点,此机柜再放一个不同的结点, 然后在另一个机柜放一个结点。这样的策略砍掉了机柜内部写操作的传输,这将提高了写的性能。机柜坏掉的概率比一个结点坏掉的概率要小的多;这个策略不会影 响数据的可靠性和可用性的保证。 实际上,当从两个不同的机柜上读数据块的时候,对比从三个上读,并不减少总使用带宽。使用此策略,文件的复制品不能跨机柜均匀的分配。
1/3的复制品放在一个结点上,(这样就有)2/3复制品放在同一个机柜上,最后的1/3均匀的放在其他的机柜的结点 上。
这个策略提高了写的性能而没有对数据可靠性或读性能造成损失。 当前,缺省的复制品放置策略,也就是这里讨论的策略还是一个正在进行中的工作。
为 了减少总带宽消耗和读延时,HDFS会试图使用离读客户最近的复制品 来满足读请求。如果在读结点的同一个机柜有一个复制品,那么这个复制品将是最合适满足这个读请求的。如果HDFS机群跨了多个数据中心,那么驻留在本地数 据中心的复制品就比远程的复制品更合适。
启 动的时候,名字结点进入一个特殊的状态叫做安全模式,此时不会出现数 据块的复制。名字结点会收到数据结点的心跳和数据块报告。数据块报告包括一个数据结点所拥有的数据块列表。每个数据块里都有指定数目的复制品。当某个名字 结点登记过数据复制品的最小数目,数据块就被认为是安全复制了。在那么可配置百分比安全复制的数据块在名字结点登记后(加上附加的30秒),名字结点退出 安全模式。它将确定数据块(如果有的话)比指定的复制品数据要少的那些,然后对这些数据块进行复制。
HDFS 的命名空间存储在 名字结点上,名字结点使用叫做“编辑日志”的事务日志来持久化记录文件系统元数据的每次变化。例如,当在HDFS中创建一个文件的时候,名字结点就会在 “编辑日志”中插入一条记录。类似的,当文件的复制因子也会引起一条新的记录被插入“编辑日志”。名字结点使用本地操作系统的文件才存储“编辑日志”。整 个文件系统的命名空间,包括块到文件的影射,文件系统的属性,都存储在一个叫做“文件系统镜象”的文件里,这个文件也是放在名字结点本地操作系统上的。
名 字结点在内存里保持一份含有整个系统的命名空间以及文件块影射的镜象。关键的元数据条目设计的很简洁,这样一个有 4GB内存的名字结点就足以支持大量的目录和文件。当名字结点启动的时候,它会从磁盘读取“文件系统镜象”和“编辑日志”,把“编辑日志”的事务都应用到 内存中的文件镜象上,然后在新的文件镜象刷新到硬盘上,这时因为事务因为已经被持久化了,就可以把旧的“编辑日志”截短了。这个过程叫做检查点。在当前的 实现中,检查点只出现在名字结点启动的时候,关于在未来支持周期性检查点的工作还在进行中。
数据结点使用本地文件系统来 存储HDFS的数据。数据结点对HDFS的文件一无所知,它只是用一个个文件存储HDFS的 每个数据块。数据结点并不在同一个目录中创建所有的文件,而是用一个启发式算法来确定每个目录的最佳文件个数,并适当的建立字目录。在同一个目录建立所有 的文件不是最理想的,这是因为本地文件系统可能不支持在同一个目录放数目巨多的文件。当数据结点启动的时候,它会遍历本地文件系统,会产生一份HDFS数 据块和本地文件对应关系的列表,并把这个报告发给名字结点:这就是块报告。
HDFS 的所有通信协议都是在TCP/IP协议上层分层的。客户去连接 名字结点上一个可配置的TCP端口,使用“客户协议”与名字结点交互。数据结点和名字结点使用“数据结点协议”交互。一个远程过程调用(RPC)则封装了 这两个协议。按照设计,名字结点永远不会启动任何的RPC,它只负责响应数据结点或客户发起的请求。
HDFS的首要目的就是要保证数据的可靠性,甚至出错的时候也是。三个 最常见的错误就是,名字结点或数据结点故障,和网络断开。
每 个数据结点都周期性的向名字结点发送心跳数据包。网络阻断可能会造成 一些数据结点失去到名字结点的连接。名字结点通过心跳的丢失来检测这样的情况。名字结点会标记没有最近没有心跳的数据结点为宕机,并不转发给他们任何新的 IO请求。任何注册在已宕机数据结点的数据对HDFS来说都是不在可用的了。数据结点的宕机会造成一些数据块的复制因子下降并低于指定值。名字结点会一直 跟踪哪些数据块需要被复制,并在需要的时候开始复制。这样必要的重复制的引发可能有多种原因:数据结点不可用,一个复制品损坏,数据结点上某个磁盘损坏, 某个文件复制因子被提升了。
HDFS 的结构是和数据重配平方案相适应的。如果某个数据结点的剩余磁 盘空间下降到某个极限,方案自动把数据从此数据结点移动到另一个结点。当出现对某个文件有很高的需求的时候,方案会动态增加更多的复制品,并平衡机群中的 其他数据。这些数据配平方案还没有实现。
有种可能 是从数据结点拿到的数据却是损坏的,这样的错误可能是由于存储 设备错误,网络故障或者软件的BUG。HDFS的客户软件实施对HDFS文件内容的校验和检查。当一个客户创建HDFS文件,它先计算文件每个块的校验 和,并存储到同命名空间下的隐藏文件里。 当客户收到文件内容后,会检查各个数据结点取出的数据和相应的校验和相匹配。如果不匹配那么客户就选择其他有复制品的数据结点取一份数据。
- “文件系统镜象”和“编辑日 志”是HDFS的中心重要结构,这些文件损坏了会导致HDFS实例不可用。
因 此,名字结点可以配置为支持保存“文件系统镜象”和“编辑日志”的多份拷贝。它们的每次更新,都会引发文件的多份拷 贝的同步更新。但是这样的同步会降低名字结点上命名空间的传输速度。实际上,变慢的程度是可以接受的,因为即便是程序是对数据非常的敏感,但是也不是对元 数据敏感。当名字结点重新启动的时候,它回选择最新的文件拷贝。 名字结点机器只是HDFS机群的一个单点故障。如果名字结点真的宕掉了,那么手动干预就是必须的了。当前,对命名结点自动重启或把宕掉的软件恢复到其他机 器上还不支持。
快照支持存储某一点时间的数据拷贝。这个特性的一个应用就是:把损坏的 HDFS实例回滚到以前某个正常的时间点。目前还不支持这个特性,未来版本会支持。
HDFS 被设计为支持非常大的文件。并且与HDFS相一致的程序也是 处理大数据集的。程序一次性写入数据,但是会一次或多次读取,并希望能得到线速的读取。HDFS支持文件语义上一次写多次读,它所使用的块大小通常是 64M。因此,HDFS的文件都被切割为64M的块,还有可能,每个数据块驻留在不动的数据结点上。
客 户创建文件的请求不是立即到达名字结点,而是HDFS客户把数据缓 存到本地的一个文件里。程序的写操作显式重定向到这个本地临时文件。当本地的文件积聚的数据超过了HDFS数据块的大小客户才和名字结点联系。名字结点在 系统的体系中插入文件名,并申请一个数据块给它。名字结点应答给客户数据结点的的ID和目标数据块ID,这样客户就把数据从本地的缓存刷新到目的的数据块 中。当文件关闭后,临时文件中剩余的未刷新数据也会被传输到数据结点中,客户这时就可以告诉名字结点文件被关闭了。这一时间点,名字结点完成了在持久存储 中创建文件的操作。如果名字结点在文件关闭之前宕掉了,那么文件就丢失了。
在对运行HDFS在上应用 软件仔细权衡以后,上述的方法已经被接受了。这些程序需要流式写入到文件。如果客户直接写到远程的文件而没有任何缓存的话,网络中的速度和拥塞就会对输出 影响很大。这样的方法也不是没有先例。早期的分布文件系统比如,AFS就已经采用了客户缓存来提高性能。为了得到数据上传的更好性能,POSIX的相关要 求已经被放弃不用了。
当客户要写 数据到HDFS的文件中,就象前一节解释的那样,数据会首 先写到一个本地文件里。假设HDFS文件的复制因子是3,当本地文件积聚到数据块那么大的时候,用户从名字结点获得一个数据结点列表,列表中的数据结点都 将保存那个数据块一份拷贝。客户就把数据块刷新到第一个数据结点上,这个结点开始用(4K)的小块来接收数据,把每个块写到本地库中,并传递给列表中的第 二个数据结点,第二个结点开始每个小数据块,写到自己本地库中,并把这块数据刷新给第3个结点。最后,第3个结点把数据写到自己的库中。因此,数据结点就 可以同时从前一个结点那里收数据,并同时流水线的把数据传给后面的数据结点。也就是,数据形成了流水线,从一个数据结点传递给下一个。
从应用程序有很多方式访 问HDFS,自然而然的,它提供了一组Java API供程序使用。 并且对这组API的C语言封装也是可用的。HTTP浏览器也可以用来浏览一个HDFS实例的文件。使用WebDAV协议访问的工作还在进行中。
HDFS使用文件和目录的形式组织用户的数据,它提供了命令接口 DFSShell让用户和其中的数据交互。这些命令的语法和其他用户已经熟悉的Shell都很相似,这里提供了一个示例:
HDFS 管理命令组是为了管理一个HDFS机群而设计的,这些命令只 能由管理员来使用,这里是一些示例: Action Command Put a cluster in SafeMode bin/hadoop dfsadmin -safemode enter Generate a list of Datanodes bin/hadoop dfsadmin -report Decommission Datanode datanodename bin/hadoop dfsadmin -decommission datanodename
一个典型的HDFS安装会配置一个WEB服务器开放自己的命名空间, 其TCP端口是可配的。这样用户就可以通过WEB浏览器遍历HDFS的命名空间并查看文件内容。
当 文件被用户或者程序删除了,并不是立即就从HDFS中移走了。而是 HDFS先把它移动到/trash目录里。只要还在这个目录里,文件就可以被恢复。文件在这个目录里的时间是可以配置的,超过了生命周期,系统就把它从命 名空间中删除了。文件的删除操作会引起相应数据块的释放。注意一点:从用户执行删除操作到从系统中看到剩余空间的增加可能需要相当长的时间。
用 户可以在删除后取消操作,只要文件还在回收站里。当用户想取消的时候,可以浏览这个目录,并取回文件。这个目录只包 含最近被删除的文件,这个目录有个特性就是HDFS使用策略自动删除文件。当前默认的策略是:超过6个小时以后自动删除文件。在未来版本里,这个策略是一 个通过良好定义的接口来配置的。
当 一个文件发复制因子减低了,名字结点会选出一些多处的可以删除的复 制品。下一个心跳将传递这些信息到数据结点,数据结点就删除相应的块,机群中就会出现相应的剩余空间。再一次说明,当调用setReplication函 数和看到剩余空间之间会有一个延时。
HDFS Java API: http://lucene.apache.org/hadoop/api/ HDFS source code: http://lucene.apache.org/hadoop/version_control.html
问题: 1) 名字结点的稳定性 2) 多进程同时访问的安全性 3) 小文件怎么解决