存储系统如何适配 Hadoop?
Posted YRCloudFile
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了存储系统如何适配 Hadoop?相关的知识,希望对你有一定的参考价值。
近年来,Hadoop 相关的大数据框架非常成熟,应用广泛。与此同时,Hadoop 默认的存储组件 HDFS 开始逐渐暴露出自己的短板:存算一体带来的资源不匹配,NameNode 的扩展瓶颈等等。
因此,Hadoop 的存算分离成为了热门趋势。使用者开始用对象存储、分布式文件存储等存储产品,来替代 HDFS,在规避了 HDFS 的同时,又能利用好其他存储系统的优势特性。
那么,存储系统应该如何适配 Hadoop 呢?
官方指南
1、适配方案
目前,Hadoop 官方给出的存储兼容方案,主要有两个文档:
HCFS (https://cwiki.apache.org/confluence/display/HADOOP2/HCFS)
文档中定义了分布式文件系统适配 Hadoop 的两种方式:
All such filesystems (including HDFS) must link up to Hadoop in two ways.
- The filesystem looks like a "native" filesystem, and is accessed as a local FS, perhaps with some filesystem-specific means of telling the MapReduce layer which TaskTracker is closest to the data.
- The filesystem provides an implementation of the org.apache.hadoop.fs.FileSystem class (and in Hadoop v2, in implementation of the FileContext class
即:
- 将文件系统作为“原生”文件系统。按照本地磁盘的方式进行访问。
- 文件系统提供一个org.apache.hadoop.fs.FileSystem类,供 Hadoop 应用进行访问。
第一种方式很好理解,就是通过其他文件系统挂载到本地目录,然后按照本地目录的方式去使用。但是这种方式也存在着一定的局限——它可以完成基本的功能,但是无法针对计算场景做额外的缓存。
第二种是目前主流的方式,通过实现 FileSystem 接口,与自定义的存储系统进行交互。因为最终实现的 jar 包会部署在计算节点上,所以可以针对性地做一些优化工作,比如数据预读、支持不同的写缓存策略,或是更复杂的分布式缓存等等。
还有另外一种方式文档中没有介绍,就是通过实现 HDFS 的后端服务来进行对接。这种方式相对来说使用比较少,我们会在最后做简要介绍。
接下来,详细介绍一下 FileSystem 目前的设计方式,以及如何去实现相关的功能。
2、接口文档
Hadoop 官方在用户手册中,详细介绍了相关的接口,包括接口前置条件、完成表现、原子性要求、一致性要求等等。详细文档地址如下:
https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/filesystem/index.html
但是,在开发初期,并不建议直接看这个文档,原因是:
- 第一,内容非常繁琐,同名的系列函数会逐一介绍。完全看完耗时很久,而且在关注细节的过程中会失去对整体的概念;
- 第二,目前文中有部分列出的接口已经可以实现了,并不需要过多关注。另外它们基于某个其他抽象接口实现的功能,你只需要实现抽象接口即可;
- 第三,文档的内容,与实际代码接口有所差异,并且文章中多处写到,如果文档与 HDFS 有所差异,以 HDFS 为准;
- 基于上述原因,建议开发者直接从 Hadoop 的源码,或其他适配的存储系统的适配代码着手,开始了解相关设计。
FileSystem 的接口设计
1、Hadoop 调用的接口分为 1.x 的 FileSystem 和 2.x 的 FileContext。
Hadoop 1.x 接口 FileSystem
FileSystem 的实现,可以分为两类:
- 实际功能类实现
Hadoop 已经内置支持了很多的存储系统,例如本地文件系统 RawLocalFileSystem,基于 AmazonS3 的 S3AFileSystem,以及基于 FTP 的 FTPFileSystem 等等。新的存储系统做适配,也要采用这种方式来做实现。
- 装饰器类实现
FilterFileSystem 本身并没有实现具体的行为,而是调用一个 FileSystem 对象接口,起到了装饰器的功能。它主要用于派生类实现额外的功能逻辑,而不需要关注底层的具体存储系统。
2、Hadoop 2.x 接口 FileContext
当你看到 1.x、2.x 接口的时候,可能会想是不是需要实现两份代码?不需要担心,Hadoop 的接口设计很好地避免了这个问题。FileContext 本身并不是接口,它通过调用 AbstractFileSystem 的接口来完成功能。AbstractFileSystem 的实现分为三种:
- DelegateToFileSystem:这个类中将所有 2.x 接口的函数使用了 1.x 的 FileSystem 做了实现。因此,我们并不需要再把 1.x 的任务重复一遍,只需要继承这个类,做一些我们期望的接口改动即可;
- FilterFs:同 1.x 的 FilterFileSystem,起到装饰器的功能;
- 其他:如果不希望直接用 1.x 接口来做实现,直接继承 AbstractFileSystem 来实现功能也没有问题。
存储系统的常见适配方式
了解完 Hadoop 的接口之后,还需要考虑在实现中如何与自己的存储对接,具体指的是和存储系统的架构、功能考量、开发量考量等等问题。目前,有很多存储系统已经做了支持,我们可以做一些了解,作为参考,大致可以分为以下几类:
实现方式 | 详细描述 | 优点 | 缺点 |
LocalFS + 挂载 | 将存储系统挂载为本地目录 |
|
|
ToPosixFileSystem + 挂载 | 将存储系统挂载为本地目录。实现 FileSystem 的时候,转为本地目录的操作。 虽然看起来和 LocalFS 似乎一样,但是 FileSystem 在实现的时候可以做扩展、优化。 |
|
|
ToServerFileSystem | FileSystem 作为一个客户端来实现,直接与存储系统后端进行交互。 这里边又可以细分为几种:
|
|
|
HDFSServer | 即实现支持 HDFS 协议的后端服务。 相对来说最繁琐的方式,需要对 HDFS 的代码有深入了解,并且需要 HDFS 后端服务可以很好地与存储系统本身做对接。 |
|
|
后续扩展
本文只对存储系统对接 Hadoop 做了简单的基础性功能介绍。如果后续想要进一步优化,可以在分布式缓存、扩展性、预读策略、输出缓存策略等方面去做额外的工作。感兴趣的还可以参考目前市面上一些好的案例,例如 Hadoop 自带的各种对象存储的实现。
以上是关于存储系统如何适配 Hadoop?的主要内容,如果未能解决你的问题,请参考以下文章