虽然文档内所涉及的版本有点旧,但内容很精彩,值得推荐
背景
在 Hadoop 中有一个抽象文件系统的概念,它有多个不同的子类实现,由 DistributedFileSystem 类代表的 HDFS 便是其中之一。在 Hadoop 的 1.x 版本中,HDFS 存在 NameNode 单点故障,并且它是为大文件的流式数据访问而设计的,不适合随机读写大量的小文件。本文将探讨通过使用其他的存储系统,例如 OpenStack Swift 对象存储,作为 Hadoop 的底层存储,为 Hadoop 的存储层增加对 OpenStack Swift 的支持,并给出测试结果,最终达到功能验证(Functional POC)的目标。值得一提的是,为 Hadoop 增加对 OpenStack Swift 的支持并非要取代 HDFS,而是为使用 Hadoop MapReduce 及其相关的工具直接分析存储在 Swift 中的数据提供了方便;本文作为一个阶段性的尝试,目前尚未考虑数据局部性(Data Locality),这部分将作为未来的工作。另外,Hadoop 2.x 提供了高可用 HDFS 的解决办法,不在本文的讨论范围之内。
本文面向的读者为对 Hadoop 和 OpenStack Swift 感兴趣的软件开发者和管理员,并假设读者已经对它们有基本的了解。本文使用的 Hadoop 的版本为 1.0.4,OpenStack Swift 的版本为 1.7.4,Swift Java Client API 的版本为 1.8,用于认证的 Swauth 的版本为 1.0.4。
Hadoop 与 OpenStack Swift 对象存储的整合
设想以下情形,如果已经在 Swift 中存储了大量数据,但是想要使用 Hadoop 对这些数据进行分析,挖掘出有用的信息。此时可能的做法是,先将 Swift 集群中的数据导出到中间服务器,再将这些数据导入到 HDFS 中,才能通过运行 MapReduce 作业来分析这些数据。如果数据量非常大,那么整个导入数据的过程会很长,并且要使用更多的存储空间。
如果能将 Hadoop 和 OpenStack Swift 进行整合,使得 Hadoop 能够直接访问 Swift 对象存储,并能运行 MapReduce 作业来分析存储在 Swift 中的数据,那么将提高效率,减少硬件成本。
Hadoop 抽象文件系统 API
org.apache.hadoop.fs.FileSystem 是 Hadoop 中的一个通用文件系统的抽象基类,它抽象出了文件系统对文件和目录的各种操作,例如:创建、拷贝、移动、重命名、删除文件和目录、读写文件、读写文件元数据等基本的文件系统操作,以及文件系统的一些其他通用操作。FileSystem 抽象类中的主要方法和含义如表 1 所示。
表 1. FileSystem 抽象类的主要方法和含义
方法签名 | 含义 |
---|---|
void initialize(URI, Configuration) | 根据配置文件对文件系统进行初始化操作 |
FSDataInputStream open(Path, int) | 打开指定路径的文件,并得到输入流 |
FSDataOutputStream create(Path, FsPermission, boolean, int, short, long, Progressable) | 创建指定路径的文件,并得到输出流 |
boolean rename(Path, Path) | 重命名文件或目录 |
boolean delete(Path, boolean) | 删除文件或目录 |
boolean mkdirs(Path, FsPermission) | 创建目录 |
FileStatus getFileStatus(Path) | 获得文件或目录的元数据 |
FileStatus[] listStatus(Path) | 获得某个目录下的所有文件或目录的元数据 |
URI getUri() | 获得该文件系统的 URI |
Path getWorkingDirectory() | 获得当前工作目录 |
void setWorkingDirectory(Path) | 设置当前工作目录 |
FileSystem 抽象类有多个不同的子类实现,包括:本地文件系统实现、分布式文件系统实现、内存文件系统实现、FTP 文件系统实现、非 Apache 提供的第三方存储系统实现,以及通过 HTTP 和 HTTPS 协议访问分布式文件系统的实现。其中,LocalFileSystem 类代表了进行客户端校验和的本地文件系统,在未对 Hadoop 进行配置时是默认的文件系统。分布式文件系统实现是 DistributedFileSystem 类,即 HDFS,用来存储海量数据,典型的应用是存储大小超过了单台机器的磁盘总容量的大数据集。第三方存储系统实现是由非 Apache 的其他厂商提供的开源实现,如 S3FileSystem 和 NativeS3FileSystem 类,它们是使用 Amazon S3 作为底层存储的文件系统实现。
通过阅读 Hadoop 的文件系统相关的源代码和 Javadoc,并借助于工具,可以分析出 FileSystem 抽象类的各个抽象方法的含义和用法,以及 FileSystem API 中各类之间的继承、依赖关系。org.apache.hadoop.fs 包中包括了 Hadoop 文件系统相关的接口和类,如文件输入流 FSDataInputStream 类和输出流 FSDataOutputStream 类,文件元数据 FileStatus 类,所有的输入/输出流类都分别和 FSDataInputStream 类和 FSDataOutputStream 类是组合关系,所有的文件系统子类实现均继承自 FileSystem 抽象类。
图 1. Hadoop FileSystem API 类图
以 S3FileSystem 为例,它使用的底层存储系统是 Amazon S3,继承了 FileSystem 抽象类,是它的一个具体实现,并实现了针对 Amazon S3 的输入/输出流。用户可以在 Hadoop 的配置文件 core-site.xml 中为 fs.default.name 属性指定 Amazon S3 存储系统的 URI,就可以使 Hadoop 得以访问 Amazon S3,并在其上运行 MapReduce 作业。
Swift 的 Java 客户端 API
Swift 通过 HTTP 协议对外提供存储服务,有一个 REST 风格的 API。Swift 本身是用 Python 语言实现的,但是也提供了多种编程语言的客户端 API,例如ÿ