Flink技术内幕之文件系统

Flink 通过 org.apache.flink.core.fs.FileSystem 类有自己的文件系统抽象。 这种抽象提供了一组通用的操作和跨各种类型的文件系统实现的最小保证。

FileSystem 的可用操作集非常有限,以支持广泛的文件系统。 例如,不支持追加或改变现有文件。

文件系统由文件系统方案标识,例如 file://、hdfs:// 等。

本文翻译自:https://nightlies.apache.org/flink/flink-docs-release-1.15/zh/docs/internals/filesystems/

实现

Flink 直接实现文件系统,文件系统方案如下:

  • file,代表机器的本地文件系统。

其他文件系统类型由桥接到 Apache Hadoop 支持的文件系统套件的实现访问。 以下是示例的不完整列表:

  • hdfs:Hadoop分布式文件系统
  • s3、s3n 和 s3a:Amazon S3 文件系统
  • gcs:谷歌云存储

如果 Flink 在类路径中找到 Hadoop 文件系统类并找到有效的 Hadoop 配置,它会透明地加载 Hadoop 的文件系统。 默认情况下,它会在类路径中查找 Hadoop 配置。 或者,可以通过配置条目 fs.hdfs.hadoopconf 指定自定义位置。

持久性保证

这些 FileSystem 及其 FsDataOutputStream 实例用于持久存储数据,既用于应用程序的结果,也用于容错和恢复。 因此,明确定义这些流的持久性语义至关重要。

持久性保证的定义

如果满足两个要求,则写入输出流的数据被认为是持久的:

可见性要求:必须保证在给定绝对文件路径时,能够访问文件的所有其他进程、机器、虚拟机、容器等都能一致地看到数据。 此要求类似于 POSIX 定义的 close-to-open 语义,但仅限于文件本身(通过其绝对路径)。

持久性要求:必须满足文件系统的特定持久性/持久性要求。 这些特定于特定的文件系统。 例如,{@link LocalFileSystem} 不为硬件和操作系统的崩溃提供任何持久性保证,而复制的分布式文件系统(如 HDFS)通常保证存在最多 n 个并发节点故障时的持久性,其中 n 是复制 因素。

对于文件流中的数据被认为是持久的,不需要完成对文件父目录的更新(以便在列出目录内容时显示文件)。 这种放松对于目录内容的更新只是最终一致的文件系统很重要。

一旦对 FSDataOutputStream.close() 的调用返回,FSDataOutputStream 必须保证写入字节的数据持久性。

示例

  • 对于容错分布式文件系统,一旦数据被文件系统接收并确认,数据就被认为是持久的,通常是通过复制到一定数量的机器(持久性要求)。 此外,绝对文件路径必须对可能访问该文件的所有其他机器可见(可见性要求)。

    数据是否命中存储节点上的非易失性存储取决于特定文件系统的具体保证。

    对文件父目录的元数据更新不需要达到一致状态。 允许某些机器在列出父目录的内容时看到该文件,而其他机器则没有,只要在所有节点上都可以通过其绝对路径访问该文件。

  • 本地文件系统必须支持 POSIX close-to-open 语义。 因为本地文件系统没有任何容错保证,所以不存在进一步的要求。

    上面特别暗示,从本地文件系统的角度来看,当被认为是持久的时,数据可能仍然在 OS 缓存中。 导致操作系统缓存丢失数据的崩溃对本地机器来说是致命的,并且不在 Flink 定义的本地文件系统保证范围内。

    这意味着仅写入本地文件系统的计算结果、检查点和保存点不能保证可以从本地机器的故障中恢复,从而使本地文件系统不适合生产设置。

更新文件内容

许多文件系统要么根本不支持覆盖现有文件的内容,要么在这种情况下不支持更新内容的一致可见性。 出于这个原因,Flink 的 FileSystem 不支持附加到现有文件,或在输出流中查找,以便可以在同一个文件中更改先前写入的数据。

覆盖文件内容

覆盖文件通常是可能的。 通过删除文件并创建新文件来覆盖文件。 但是,某些文件系统无法使该更改对所有有权访问该文件的各方同步可见。 例如,Amazon S3 仅保证文件替换可见性的最终一致性:有些机器可能会看到旧文件,有些机器可能会看到新文件。

为了避免这些一致性问题,Flink 中故障/恢复机制的实现严格避免多次写入同一个文件路径。

线程安全

FileSystem 的实现必须是线程安全的:同一个 FileSystem 实例经常在 Flink 中的多个线程之间共享,并且必须能够同时创建输入/输出流和列出文件元数据。

FSDataOutputStream 和 FSDataOutputStream 实现严格来说不是线程安全的。 流的实例也不应该在读取或写入操作之间的线程之间传递,因为不能保证跨线程操作的可见性(许多操作不会创建内存栅栏)。

0 0 投票数
文章评分

本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://lrting.top/backend/6590/

(0)
上一篇 2022-06-18 13:04
下一篇 2022-06-19 23:24

相关推荐

订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x