速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

Netflix Drive:构建媒体资产云原生文件系统

作者:Tejas Chopra

  • 2022-06-17
  • 本文字数:6034 字

    阅读完需:约 20 分钟

Netflix Drive:构建媒体资产云原生文件系统

Netflix Drive 是一个多接口、多操作系统的云文件系统,目的是在工作室艺术家的工作站上提供典型 POSIX 文件系统的外观和体验。

 

它有 REST 端点,行为和微服务类似。它有许多供工作流使用的后端动作以及自动化用例(用户和应用程序不直接处理文件和文件夹)。REST 端点和 POSIX 接口可以在任何 Netflix Drive 实例中共存,并不相互排斥。

 

Netflix Drive 配有事件告警后端(作为框架的一部分)。在 Netflix Drive 中,事件和告警是一等公民。

 

我们将 Netflix Drive 打造成了一个通用框架,这样用户就可以插入不同类型的数据和元数据存储。例如,让 Netflix Drive 使用 DynamoDB 作为元数据存储后端,并使用 S3 作为数据存储后端。使用 MongoDB 和 Ceph Storage 作为后端数据存储和元数据存储。要了解关于这个框架的更多细节,请观看完整的视频演示

为什么构建 Netflix Drive

一般来说,Netflix 开创了云上娱乐工作室的概念,目的是为了让世界各地的艺术家都可以在上面工作并开展合作。要做到这一点,Netflix 需要提供一个分布式、可扩展且性能良好的平台基础设施。

 

在 Netflix,资产是数据、元数据文件和文件夹集合,这些文件和文件夹由不同的系统和服务存储和管理。

 

以拍摄为起点,即相机录制视频(产生数据),直到数据进入电影和电视节目,不同系统基于创作流程给这些资产加上了各种元数据。

 

艺术家在边缘端使用资产,他使用的应用程序需要一个接口,以便无缝地访问这些文件和文件夹。这个简单的工作流不只局限于艺术家,也延伸到了工作室。内容渲染期间发生的资产转换就是一个很好的例子,该过程使用了 Netflix Drive。

 

工作室的工作流需要在创作迭代的各个阶段之间转移资产。每个阶段的断言都被标记为新的元数据。我们需要有一个系统,支持向数据添加不同形式的元数据。

 

我们还需要可以在每个阶段改变的动态访问控制等级,使得平台只向某些应用程序、用户或工作流暴露特定的资产子集。然而 AWS 存储网关在性能和安全方面不符合我们的要求。

 

为了满足多种场景下需求,我们设计了 Netflix Drive。该平台可以作为一个 POSIX 文件系统,在云端存储数据并从云端检索数据,它有一个功能更丰富的控制接口。它是存储基础设施的基础组成部分,可以满足许多 Netflix 工作室和平台的需求。

Netflix Drive 的架构

Netflix Drive 提供了许多接口,如图 1 所示:



图 1:Netflix Drive 的基本架构

 

POSIX 接口(图 2)支持对文件做简单的文件系统操作,如创建、删除、打开、重命名、移动等。这个接口处理 Netflix Drive 上的数据和元数据操作。不同应用程序、用户、脚本或工作流会读、写存储在 Netflix Drive 上的文件,或者创建文件及提出其他操作请求。这与实时文件系统类似。



图 2:Netflix Drive 的 POSIX 接口

 

另一个接口是 API 接口(图 3)。它提供了一个可控的 I/O 接口。该 API 接口是很多工作流管理工具或代理特别关注的。它暴露了 Netflix Drive 上某种形式的控制操作。工作室中使用的很多工作流都在一定程度上涉及资产或文件。它们想控制这些资产在命名空间上的投影。比如,当 Netflix Drive 在用户的机器上启动时,工作流工具最初只允许用户查看大型数据集的一个子集。这就是由这些 API 管理的。这些 API 也可用于动态操作,如将特定文件上传到云端,或动态下载一组特定的资产,并在命名空间的特定点上附加和展示它们。



图 3:Netflix Drive 的 API 接口

 

如前所述,事件(图 4)在 Netflix Drive 架构中最为重要,它包含遥测信息。比如,使用审计日志跟踪不同用户对同一个文件所做的所有操作。我们需要在云中运行的服务能够消费审计日志、度量和更新。这里使用了通用框架,允许将不同类型的事件后端接入 Netflix Drive 生态系统。

 

另外,事件接口也用于基于 Netflix Drive 进行的构建。这个接口可以创建共享文件和文件夹。



图 4:Netflix Drive 中的事件

 

数据传输层(图 5)是一个抽象概念,处理数据从 Netflix Drive 到多层存储和不同类型接口的传输。它把文件传输到艺术家工作站或机器上的 Netflix Drive 挂载点。



图 5:Netflix Drive 中的数据传输

 

出于性能考虑,Netflix Drive 不处理直接将数据发送到云端的问题。我们希望 Netflix Drive 的性能尽可能地模拟本地文件系统。因此,如果可以,尽量使用本地存储来存储文件,然后按既定的策略将数据从本地存储转移到云存储。

 

我们通过两种方式将数据转移到云端。第一种是控制接口使用动态发布 API,让工作流可以将资产的子集转移到云端。另一种是自动同步,这是一种将所有本地文件与云存储文件自动同步的能力。这与 Google Drive 存储文件的方式相同。为此,云存储分成了不同的层。图 5 列出了媒体缓存(Media Cache)和 Baggins:媒体缓存是一个具备区域感知能力的缓存层,使数据更靠近边缘用户;Baggins 是位于 S3 之上的一层,处理分块和加密内容。

 

总的来说,Netflix Drive 的架构包含用于数据和元数据操作的 POSIX 接口。API 接口处理不同类型的控制操作。事件接口跟踪所有状态变化更新。数据传输接口将在 Netflix Drive 上进进出出的数据到云端的传输进行抽象。

Netflix Drive 剖析

Netflix Drive 包含 3 个层(图 6):接口、存储后端、传输服务。



图 6:Netflix Drive 剖析

 

最上面的接口层包含所有的 FUSE 文件处理程序和 REST 端点。

 

中间是存储后端层。请记住,Netflix Drive 提供了一个框架,你可以在其中插入并使用不同类型的存储后端。这里有抽象的元数据接口和抽象的数据接口。在第一次迭代时 CDrive 作为元数据存储。CDrive 是 Netflix 自己的工作室资产感知( studio-asset-aware)的元数据存储。如前所述,Baggins 是 Netflix 的 S3 数据存储层,在将内容推送到 S3 之前对其进行分块和加密。

 

Intrepid 是传输层,将数据传输到 Netflix Drive 以及从 Netflix Drive 传出数据。Intrepid 是内部开发的高效传输协议,许多 Netflix 应用程序和服务都用它来将数据从一个服务传输到另一个服务。Intrepid 不仅用于传输数据,而且还用于元数据存储某些方面的传输。通过这种能力来在云上保存元数据存储的一些状态。



图 7:Netflix Drive 的抽象层

 

因为我们使用的是基于 FUSE 的文件系统,libfuse 负责处理不同的文件系统操作。启动 Netflix Drive,通过清单文件以及 REST API 和控制接口对它进行引导。

 

抽象层抽象了默认的元数据存储和数据存储,可以使用不同类型的数据和元数据存储。在这个例子中,用 CockroachDB 适配器作为元数据存储,用 S3 适配器作为数据存储。此外还可以使用不同类型的传输协议,它们是 Netflix Drive 即插即用接口的一部分。协议层可以是 REST 或 gRPC。最后是实际的数据存储。



图 8:Netflix Drive 服务在本地工作站和云之间的划分

 

工作站机器上配有典型的 Netflix Drive API 和 POSIX 接口。本地工作站上的 Netflix Drive 将使用传输代理和库来与元数据存储和数据存储进行交互。

 

云服务包含元数据存储,在 Netflix 是 CDrive。媒体缓存作为存储的中间层。S3 提供对象存储。

 

注意,我们也使用本地存储来缓存读和写,以满足用户对 Netflix Drive 的高性能期待。

 

安全是 Netflix Drive 的一个关注点。许多应用程序使用这些云服务;它们位于 Netflix 的所有资产库之前。确保这些资产的安全,并且只允许有适当权限的用户查看允许他们访问的资产子集,这一点至关重要。因此,Netflix Drive 上使用了双因素认证。

 

安全是基于 CockroachDB 构建的一个层。Netflix Drive 利用了 Netflix 内部的一些安全服务,目前没有可以插入的外部安全 API。我们计划在发布任何开源版本之前把它们抽象出来,这样任何人都可以构建可插拔的模块来进行处理。

Netflix Drive 典型的生命周期

鉴于 Netflix Drive 能够动态地呈现命名空间,并将不同的数据存储和元数据存储汇集在一起,因此必须考虑其生命周期。

 

最初通过清单启动 Netflix Drive,而这个初始清单可能是空的。工作站或工作流从云端下载资产,并将这些内容预加载到 Netflix Drive 的挂载点。工作流和艺术家修改这些资产,Netflix Drive 会定期用公开的 API 进行快照,或者使用自动同步功能将这些资产上传到云端。

 

在启动过程中,Netflix Drive 通常要求指定一个挂载点。它使用用户的身份进行认证和授权。它创建本地存储的位置(文件将被缓存在那里),以及端点的云元数据存储和数据存储。清单包含用于预加载内容的可选字段。

 

使用 Netflix Drive 的应用程序和工作流有不同的类型,每一种角色都有自己的特点。例如,有的应用程序可能特别依赖 REST 控制接口,因为它知道资产,所以会直接使用 API 将文件上传到云端。其他应用程序可能不知道何时将文件上传到云端,所以会依靠自动同步功能在后台上传文件。这些都是 Netflix Drive 的每个角色所定义的各种可选方案。



图 9:Netflix Drive 的引导程序清单示例

 

图 9 展示了一个引导程序清单示例。定义好本地存储之后,Netflix Drive 声明了实例。每个挂载点可以有多个不同的 Netflix Drive 实例。这里使用了两个实例:一个动态实例和一个用户实例,每个实例有各自的后端数据存储和元数据存储。动态实例使用 Redis 元数据存储和 S3 数据存储。用户实例使用 CockroachDB 元数据存储和 Ceph 数据存储。为实现数据持久化,Netflix Drive 为每个工作空间分配了一个唯一标识。



图 10:Netflix Drive 命名空间的静态设置

 

Netflix Drive 的命名空间是可以查看所有文件的地方。Netflix Drive 可以静态或动态地创建命名空间。静态方法(图 10)准确指定了要在引导时预下载到当前实例的文件。为此,我们提供了一个文件会话和容器信息。工作流可以用文件预先填充 Netflix Drive 挂载点,这样后续的工作流就可以以此为基础进行构建。

 

创建命名空间的动态方法是在 REST 接口中调用 Netflix Drive API(图 11)。在本例中,stage API 暂存文件以及从云存储中拉取文件,然后将它们附加到命名空间中的特定位置。这些静态和动态接口并不相互排斥。



图 11:Netflix Drive 命名空间的动态设置

更新内容

Netflix Drive 的 POSIX 操作可以完成文件的打开/关闭、移动、读/写等动作。

 

此外,REST API 的一个子集也可以修改文件——例如,API 可以暂存文件,从云中拉取文件。可以设置文件检查点,可以保存文件,显式地将文件上传到云存储。

 

图 12 展示了如何使用 Publish API 将文件上传到云上。我们可以自动保存文件,即定期检查文件并上传到云上,还可以执行显式保存,显式保存是一个 API,不同的工作流可以调用它来发布内容。



图 12:Netflix Drive 的 Publish API

 

使用不同 API 的一个很好的例子是当艺术家处理大量瞬息数据时。这些数据中的大部分都不需要上传云端,因为这些数据还只是过程数据,不是最终产品。对于这样的工作流,显式保存更合适,而不是自动保存(即 Google Drive 保存文件的方式)。一旦艺术家确定内容已经可以分享给其他艺术家或工作流,就可以调用这个 API 将其保存到云端。该 API 将在艺术家的 Netflix Drive 挂载点中生成选定文件的快照,并将它们传送到云端,存储在适当的命名空间下。

经验教训

多个角色在不同类型的工作流中使用 Netflix Drive,这在开发过程中教会了我们很多东西。在设计架构时遇到了多个需要考虑的点。

 

文件、工作流和艺术家工作站的性能/延迟要求——以及我们希望为使用 Netflix Drive 的艺术家提供的体验——决定了许多架构选择。我们用 C++实现了很多代码。比较各种语言,我们认为 C++的性能最好,这是重点关注的一个方面。没有使用 Rust 是因为那时 Rust 还没有充分支持 FUSE 文件系统。

 

我们希望 Netflix Drive 成为一个通用框架,任何插入数据存储和元数据存储都可以接受。为多个操作系统设计通用框架非常困难。在研究了其他可选方案之后,我们决定在 CentOS、macOS 和 Windows 上使用基于 FUSE 的文件系统来支持 Netflix Drive。这成倍地增加了测试矩阵和支持矩阵。

 

我们使用不同的后端,拥有不同的缓存和分层。依赖缓存的元数据操作。Netflix Drive 服务 EB 级数据和数十亿项资产,可扩展性设计是架构的基石之一。在云上扩展解决方案的瓶颈是数据存储。但是元数据存储才是瓶颈。可扩展性的关键是处理元数据。我们非常关注元数据管理,降低元数据存储的调用次数。在本地缓存大量数据可以提高工作室应用程序和工作流的性能。通常,这些应用程序和工作流需要大量的元数据。

 

我们探索在云中使用文件系统(如 EFS)。但是,文件系统扩展到一定程度时会影响性能。为了服务于数十亿项资产,需要使用某种形式的对象存储,而不是文件存储。这意味着艺术家所熟悉的文件必须被转换成对象。最简单的方法是在文件和对象之间建立起一对一映射——尽管这样做很简单,但文件大小可能会超过支持的最大对象的大小。我们需要将一个文件映射到多个对象。如果艺术家改变了文件中的一个像素,Netflix Drive 只需要改变包含相关块的对象。构建转换层是一种权衡,是为了可扩展性。

 

对象的使用带来了数据去重和分块的问题。对象存储使用版本控制:对象的每次更改,无论更改多小,都会创建对象的新版本。按照惯例,哪怕是文件中的一个像素发生了变化,也要发送整个文件并将其作为一个对象重新写入。你不能只是发送增量并将其应用到云存储上。通过将一个文件分成多个对象,可以缩小必须发送到云端的对象。选择合适的块大小与其说是一门科学,不如说是一门艺术,因为许多较小的块意味着管理大量数据和大量转化逻辑,元数据的数据量会增加。另一个需要考虑的问题是加密。我们对每个数据块进行加密,所以数据块越小越多,加密密钥和元数据就越多。块大小可以在 Netflix Drive 中配置。

 

多层存储可以提高性能。在设计 Netflix Drive 时,我们并没有局限于本地存储或云存储。构建它是为了可以轻松地将不同的存储层添加到 Netflix Drive 框架中。这体现在设计、架构和代码中。例如,媒体缓存只是一个媒体存储,缓存层更接近于用户和应用程序。Netflix Drive 在本地文件存储中缓存了很多数据,而 Google Drive 不是这样做的。因此,和他们相比,可以有更好的本地文件系统性能。

 

这是我们拒绝 AWS 存储网关的另一个原因。如果多位艺术家同时处理一项资产,并且该资产的每次迭代都存储在云端,那么云成本将会激增。我们希望这些资产存储在离用户较近的媒体缓存(这是只有 Netflix 才有的东西)中,并控制最终副本何时进入云端。利用这种混合基础设施,这些参数可以通过 AWS 存储网关获得。

 

软件架构的栈式方法至关重要。共享命名空间就是一个很好的例子。目前,我们正致力于提升在不同工作站或艺术家之间共享文件的能力。我们以事件框架为基础进行构建,而后者已被设计成 Netflix Drive 架构本身的一部分。当 Netflix Drive 实例上的一个用户将一个文件添加到特定的命名空间时,它会生成一个可供不同云服务使用的事件。然后,Netflix Drive 会使用 REST 接口将该文件注入到访问该命名空间的其他 Netflix Drive 实例中。

 

如果你想了解更多有关 Netflix Drive 的信息,请查阅技术博客

 

我们努力争取明年开源 Netflix Drive。许多希望在云端创建工作室的人都联系了我们,他们希望使用 Netflix Drive 的开源版本,并针对其用例构建可插拔模块,这个问题会优先考虑。


作者简介:

Tejas Chopra 是 Netflix 数据存储平台团队的一名资深软件工程师。

 

原文链接:

Netflix Drive: Building a Cloud-Native Filesystem for Media Assets

2022-06-17 08:063349

评论

发布
暂无评论
发现更多内容

设计与思考,关于资源和生命周期(三)

程序员架构进阶

设计模式 架构设计 28天写作 3月日更 池化技术

架构师知识笔记2

felix徐

Go语言的初体验

Phoenix

Go 语言

go-admin开源项目分析-1[安装、配置、启动]

happlyfox

学习 3月日更 Go 语言 go-admin

Vue3源码 | 如何挂载组件元素?

梁龙先森

源码分析 大前端 Vue3

K8s各节点常用命令

happlyfox

学习 k8s 3月日更

Kubernetes 弃用 Docker 后如何切换到 Containerd

倪朋飞

Docker Kubernetes 微服务

MySQL-技术专题-知识点介绍

洛神灬殇

MySQL

Redis - AOF

insight

redis 3月日更

极客时间·产品训练营·第八周作业

二大爷

极客大学产品经理训练营

火爆全网!2021年最新发布Java面试清单(九大技术点)

比伯

Java 程序员 架构 程序人生 架构师

程序思维与架构思维

Simon

架构实战营

蚂蚁开源增强版 SpringBoot,都有高级特性?

Java小咖秀

开源 springboot 蚂蚁金服 SOFA

软件工程笔记:学习方法

风翱

软件工程 笔记 3月日更

那些不得不知的缓存知识

Java 缓存 程序员 面试

一篇文章让你彻彻底底理解 I/O 多路复用

Java 程序员 架构 面试 计算机

阿里二面,面试官居然把 TCP 三次握手问的这么细致

鞋子特大号

面试 TCP 三次握手 四次挥手

Python OpenCV 图像标记,取经之旅第 12 天

梦想橡皮擦

3月日更

畅玩国服LOL?MacBook M1 Windows虚拟机体验

Zhendong

arm MacBook m1

管理者如何才能不亲力亲为?

石云升

项目管理 28天写作 职场经验 管理经验 3月日更

使用雪花 id 或 uuid 作为 MySQL 主键,被老板怼了一顿!

Java小咖秀

MySQL 数据库 雪花算法 uuid 雪花id

初识Golang之条件语句

Kylin

基础语法 3月日更 Go 语言

Redis - RDB

insight

redis 3月日更

区块链如何助力中小企业解决融资难题

CECBC

区块链

10年后端开发程序员精心整理「C/C++ Linux服务器」 成长路线(附思维导图)

Linux服务器开发

Linux 后端 C/C++ Linux服务器开发 Linux后台开发

Wireshark数据包分析学习笔记Day24

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

LeetCode链表专题01: 反转链表

小马哥

Java 链表 LeetCode 数据结构与算法 七日更

一束光的旅程

脑极体

Go Modules 常见使用陷阱

Rayjun

go modules Go 语言

Redis 内存碎片清理

escray

redis 学习 极客时间 3月日更 Redis 核心技术与实战

mysql 检索分享上篇

new life

Netflix Drive:构建媒体资产云原生文件系统_语言 & 开发_InfoQ精选文章