2.1 开源的GFS——HDFS
Google的GFS(Google File System,Google文件系统)如何实现人们不得而知,但是通过开源的GFS——HDFS,读者可以对分布式文件系统进行一定程度的认识和了解。
2.1.1 设计前提与目标
HDFS的设计前提与目标有如下6个。
(1)硬件错误是常态而不是异常。HDFS被设计为运行在普通硬件上,所以硬件故障是很正常的。HDFS可能由成百上千的服务器节点构成,每个服务器节点上都存储着文件系统的部分数据,而HDFS的每个组件随时都有可能出现故障。因此,错误检测并快速自动恢复是HDFS的最核心设计目标。
(2)流式数据访问。运行在HDFS上的应用主要是以流式数据读取为主,做批量处理而不是用户交互处理,因此HDFS更关注数据访问的高吞吐量。
(3)大规模数据集。HDFS的典型文件大小可能都在GB级甚至TB级,因此HDFS支持大文件存储,并能提供整体上高的数据传输带宽,能在一个集群里扩展到数百个节点。一个单一的HDFS实例应该能支撑数以千万计的文件。
(4)简单一致性模型。HDFS的应用程序需要对文件实行一次性写、多次读的访问模式。文件一经创建、写入和关闭之后就不需要再更改了。这样的假定简化了数据一致性问题,使高吞吐量的数据访问成为可能。
(5)移动计算比移动数据更划算。对于大文件来说,移动计算比移动数据的代价要低。如果在数据旁边执行操作,那么效率会比较高,当数据特别大的时候效果更加明显,这样可以减少网络的拥塞和提高系统的吞吐量。这就意味着,把计算迁移到数据附近更好,而不是把数据传输到程序运行的地方。HDFS提供了接口,以便让程序将自己移动到数据存储的地方执行。
2.1.2 HDFS体系结构
HDFS是一个主/从(Master/Slave)体系结构,如图2-1所示。从最终用户的角度来看,它就像传统的文件系统一样,可以通过目录路径对文件执行CRUD(Create、Read、Update和Delete)操作。但由于分布式存储的性质,HDFS集群拥有一个NameNode和一些DataNodes。NameNode管理文件系统的元数据,DataNode存储实际的数据。客户端通过同NameNode和DataNodes的交互访问文件系统。客户端联系NameNode以获取文件的元数据,而真正的文件I/O操作是直接和DataNode进行交互的。
NameNode(也就是主控制服务器)负责管理文件系统的命名空间,记录文件数据块在每个DataNode上的位置和副本信息,协调客户端对文件的访问,以及记录命名空间内的改动或命名空间本身属性的改动。DataNode负责它们所在的物理节点上的存储管理。HDFS开放文件系统的命名空间以便让用户以文件的形式存储数据。HDFS的数据都是“一次写入、多次读取”,典型的块大小是64MB。HDFS的文件通常是按照64MB被切分成不同的数据块(Block),每个数据块尽可能地分散存储于不同的DataNode中。NameNode执行文件系统的命名空间操作,比如打开、关闭、重命名文件或目录,还决定数据块到DataNode的映射。DataNode负责处理客户的读写请求,依照NameNode的命令,执行数据块的创建、复制、删除等工作。例如客户端要访问一个文件,首先,客户端从NameNode中获得组成该文件的数据块位置列表,即知道数据块被存储在哪些DataNode上;然后,客户端直接从DataNode上读取文件数据。此过程中,NameNode不参与文件的传输。
图2-1 HDFS的结构示意图
HDFS典型的部署是在一个专门的机器上运行NameNode,集群中的其他机器各运行一个DataNode;也可以在运行NameNode的机器上同时运行DataNode,或者一台机器上运行多个DataNode。一个集群只有一个NameNode的设计大大简化了系统架构。
NameNode使用事务日志(EditLog)来记录HDFS元数据的变化,使用映像文件(FsImage)存储文件系统的命名空间,包含文件的映射、文件的属性信息等。事务日志和映像文件都存储在NameNode的本地文件系统中。NameNode启动时,从磁盘中读取映像文件和事务日志,把事务日志的事务都应用到内存中的映像文件上,然后将新的元数据刷新到本地磁盘的新的映像文件中,这样可以截去旧的事务日志,这个过程称为检查点(Checkpoint)。HDFS还设有Secondary NameNode节点,它辅助NameNode处理映像文件和事务日志。NameNode启动的时候合并映像文件和事务日志,而Secondary NameNode会周期地从NameNode上复制映像文件和事务日志到临时目录,合并生成新的映像文件后再重新上传到NameNode,NameNode更新映像文件并清理事务日志,使得事务日志的大小始终控制在可配置的限度下。
2.1.3 保障HDFS可靠性措施
HDFS的主要设计目标之一就是在故障情况下也能保证数据存储的可靠性。HDFS具备了较为完善的冗余备份和故障恢复机制,可以实现在集群中可靠地存储海量文件。
1.冗余备份
HDFS将每个文件存储成一系列数据块(Block),默认块大小为64MB(可配置)。为了容错,文件的所有数据块都会有副本(副本数量即复制因子,可配置)。HDFS的文件都是一次性写入的,并且严格限制为任何时候都只有一个写用户。DataNode使用本地文件系统来存储HDFS的数据,但是它对HDFS的文件一无所知,只是用一个个文件存储HDFS的每个数据块。当DataNode启动的时候,它会遍历本地文件系统,产生一份HDFS数据块和本地文件对应关系的列表,并把这个报告发给NameNode,这就是块报告(Blockreport)。块报告包括了DataNode上所有块的列表。
2.副本存放
HDFS集群一般运行在多个机架上,不同机架上机器的通信需要通过交换机。通常情况下,副本的存放策略很关键,机架内节点之间的带宽比跨机架节点之间的带宽要大,它能影响HDFS的可靠性和性能。HDFS采用机架感知(Rack-aware)的策略来改进数据的可靠性、可用性和网络带宽的利用率。通过机架感知,NameNode可以确定每个DataNode所属的机架ID。一般情况下,当复制因子是3的时候,HDFS的部署策略是将一个副本放在同一机架上的另一个节点,一个副本存放在本地机架上的节点,最后一个副本放在不同机架上的节点。机架的错误远比节点的错误少,这个策略可以防止整个机架失效时数据丢失,不会影响到数据的可靠性和可用性,又能保证性能。目前,副本存放策略还正在开发中。图2-2体现了复制因子为3的情况下,各数据块的分布情况。
图2-2 复制因子为3时数据块分布情况
3.心跳检测
NameNode周期性地从集群中的每个DataNode接受心跳包和块报告,NameNode 可以根据这个报告验证块映射和其他文件系统元数据。收到心跳包说明该DataNode工作正常。如果DataNode不能发送心跳消息,NameNode会标记最近没有心跳的DataNode为宕机,不会发给它们任何新的I/O请求。这样一来,任何存储在宕机的DataNode的数据将不再有效。DataNode的宕机会造成一些数据块的副本数下降并低于指定值,NameNode会不断检测这些需要复制的数据块,并在需要的时候重新复制。引发重新复制有多种原因:DataNode不可用、数据副本的损坏、DataNode上的磁盘错误或者复制因子增大。
4.安全模式
系统启动时,NameNode会进入一个安全模式。此时不会出现数据块的写操作。NameNode会收到各个DataNode拥有的数据块列表对的数据块报告,由此NameNode获得所有的数据块信息。数据块达到最小副本数时,该数据块就被认为是安全的。在一定比例(可配置)的数据块被NameNode检测确认是安全之后,再等待若干时间,NameNode自动退出安全模式状态。当检测到副本数不足的数据块,该块会被复制到其他数据节点,以达到最小副本数。
5.数据完整性检测
多种原因会造成从DataNode获取的数据块有可能是损坏的。HDFS客户端软件实现了对HDFS文件内容的校验和(Checksum)检查,在HDFS文件创建时,会计算每个数据块的校验和,并将校验和作为一个单独的隐藏文件保存在命名空间下。当客户端获取文件后,它会检查从DataNode获得的数据块对应的校验和是否和隐藏文件中的相同,如果不同,客户端就会认为数据块有损坏,将从其他DataNode获取该数据块的副本。
6.空间回收
文件被用户或应用程序删除时,并不是立即就从HDFS中移走,而是先把它移动到/trash目录里。只要还在这个目录里,文件就可以被迅速恢复。文件在这个目录里的时间是可以配置的,超过了这个时间,系统就会把它从命名空间中删除。文件的删除操作会引起相应数据块的释放,但是从用户执行删除操作到从系统中看到剩余空间的增加可能会有一个时间延迟。只要文件还在/trash目录里,用户可以取消删除操作。当用户想取消时,可以浏览这个目录并取回文件,这个目录只保存被删除文件的最后副本。这个目录还有一个特性,就是HDFS会使用特殊策略自动删除文件。当前默认的策略是:文件超过6个小时后自动删除,在未来版本里,这个策略可以通过定义良好的接口来配置。
7.元数据磁盘失效
映像文件和事务日志是HDFS的核心数据结构。如果这些文件损坏,将会导致HDFS不可用。NameNode可以配置为支持维护映像文件和事务日志的多个副本,任何对映像文件或事务日志的修改,都将同步到它们的副本上。这样会降低NameNode处理命名空间事务的速度,然而这个代价是可以接受的,因为HDFS是数据密集、而非元数据密集的。当NameNode重新启动的时候,总是选择最新的一致的映像文件和事务日志。在HDFS集群中NameNode是单点存在的,如果它出现故障,必须手动干预。目前,HDFS还不支持自动重启或切换到另外的NameNode。
8.快照
快照支持存储某个时间的数据复制,当HDFS数据损坏的时候,可以回滚到过去一个已知正确的时间点。HDFS目前还不支持快照功能。