爲媒體資產構建一個雲原生的文件系統

Netflix Drive: 爲媒體資產構建一個雲原生的文件系統

Netflix Drive是一個多接口、多OS的雲文件系統,旨在爲設計師的工作站提供典型的POSIX文件系統和操作方式。

它還可以作爲一個具有REST後端的微服務,內含很多工作流所使用的後端操作,以及無需用戶和應用與文件和文件夾直接交互的自動化場景。REST後端和POSIX接口可以共存於任何Netflix Drive實例中,無需手動排除。

Netflix Drive框架中採用了事件告警後端。事件和告警是Netflix Drive的一等公民。

我們將Netflix Drive定義爲通用框架,支持用戶選擇不同類型的數據和元數據存儲。例如,可以使用DynamoD作爲Netflix Drive的元數據存儲,也可以使用MongoDB和Ceph Storage作爲後端數據存儲和元數據存儲。更多參見完整的視頻演示

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

爲什麼構造Netflix Drive

總的來說,Netflix開創了雲娛樂工作室的概念,它允許全球的設計師共同協作。爲此,Netflix需要提供一個分佈式、可擴展的高性能基礎設施平臺。

在Netflix,資產指由不同的系統和服務保存和管理的、包含數據和元數據的一系列文件和目錄。

從數據採集開始,即當攝像機記錄視頻(產生數據),到數據變爲電影和電視節目,這些資產會基於創作流程,被不同的系統打上各種元數據標籤。

在邊緣(即使用資產的設計師),設計師和他們的應用會希望使用一個接口來無縫訪問這些文件和目錄。當然,該工作流並不僅適用於設計師,也適用於工作室。一個最好的例子是,在使用Netflix Drive進行內容渲染的過程中會發生資產轉換。

工作室流程中需要在不同的創作迭代階段中轉移資產,每個階段都會給資產打上新的元數據標籤。我們需要一個能夠在數據中添加不同形式的元數據的系統。

我們還需要在每個階段中支持多種級別的動態訪問控制,這樣就可以在平臺項目中限制特定應用、用戶或流程可以訪問的資產子集。我們調研了AWS Storage Gateway,但其性能和安全性無法滿足我們的需求。

最後訴求於設計Netflix Drive來滿足多種場景的需求。該平臺可以作爲一個簡單的POSIX文件系統,將數據保存到雲端或從雲端檢索數據,同時也可以包含豐富控制接口。它將成爲支持大量Netflix工作室和平臺的基礎存儲設施的一部分。

Netflix Drive的架構

圖1展示了Netflix Drive的接口:

image

圖1:Netflix Drive的基礎架構

POSIX接口(圖2)展示了簡單的針對文件的文件系統操作,如創建、刪除、打開、重命名、移動等。該接口與Netflix Drive的數據和元數據操作進行交互。不同的應用、用戶和腳本或流程可以對保存在Netflix Drive中的文件執行讀取、寫入、創建等操作,類似於其他文件系統。

image

圖2:Netflix Drive 的POSIX接口

圖3展示了其他API接口。它提供了一個可控制的I/O接口。該API接口特別適用於某些流程管理工具或代理。它暴露了某種形式的控制操作。工作室的很多流程對資產或文件都有一定的瞭解,它們希望控制投射到命名空間的資產。一個簡單的例子是,當在用戶機器上啓動Netflix Drive時,流程工具一開始會通過這類API限制用戶只能訪問一部分數據。該API還需要支持動態操作,如將特定文件更新到雲端或動態下載特定的資產集,並將其附加並展示到命名空間的特定點上。

image

圖3:Netflix Drive的API接口

如上所述,事件(圖4)位於Netflix Drive架構的最重要位置,事件包含遙測信息。典型的例子是使用審計日誌來跟蹤用戶對文件的操作。我們可能希望運行在雲端的服務能夠消費日誌、指標以及最新情報。我們使用通用框架來允許在Netflix Drive生態中插入不同類型的事件後端。

還可以在Netflix Drive之上構建事件接口。我們可以使用該接口創建共享文件和文件夾的概念。

image

圖4:Netflix Drive的事件

數據轉換層(圖5)負責將Netflix Drive的數據轉換到多個存儲層或不同類型的接口中。它可以將文件放入設計師的工作站或機器的Netflix Drive掛載點中。

image

圖5: Netflix Drive中的數據轉換

出於性能的原因,Netflix Drive不會將數據直接發送到雲端。我們希望Netflix Drive像本地文件系統一樣運行,可能的話,先保存文件,然後使用某些策略將數據從本地存儲上傳到雲端存儲。

通常我們會使用兩種方式來上傳數據。第一種方式中,控制接口使用動態觸發APIs來允許工作流將一部分資產上傳到雲端。另一種爲自動同步,即自動將本地文件同步到雲端存儲,這與Google Drive的方式相同。爲此,我們有不同的雲存儲層。圖5特別提到Media Cache和Baggins:Media Cache是一個區域感知存儲層,用於將數據傳遞給最近的邊緣用戶,Baggins位於S3之上,處理分塊和加密內容。

總之,Netflix Drive架構設計了操作數據和元數據的POSIX接口。API接口處理不同類型的控制操作,事件接口會跟蹤所有狀態變更,數據傳輸接口負責在Netflix Drive和雲端傳輸字節數據。

剖析Netflix Drive

Netflix Drive架構(圖6)包含3層:接口、存儲後端和傳輸服務。

image

圖6:剖析Netflix Drive

最上層接口包含所有的FUSE文件處理程序以及REST後端。

中間層是存儲後端層。Netflix Drive提供了一個框架來幫助安裝不同類型的存儲後端。這裏我們抽象了元數據接口以及數據接口。在第一個迭代中,我們使用CDrive作爲元數據存儲。CDrive是Netflix自有的工作室資產元數據存儲。Baggins是Netflix的S3存儲層,在將數據推送到S3之前會進行分塊和加密。

Intrepid是傳輸層,負責在雲端和Netflix Drive之間傳輸字節數據。Intrepid是一個內部開發的高效率傳輸協議,很多Netflix應用和服務會用它來傳輸數據。Intrepid不僅可以傳輸數據,還可以傳輸某些類型的元數據。我們需要這種能力來在雲端保存元數據存儲的某些狀態。

image

圖7:Netflix Drive的抽象層

圖7展示了Netflix Drive的抽象層

由於我們使用了基於FUSE的文件系統,需要使用libfuse來處理不同的文件系統操作。 我們啓動Netflix Drive,並使用清單、REST API和控制接口進行引導。

抽象層抽象了默認的元數據存儲和數據存儲。可以有不同類型的數據和元數據存儲--在下面例子中,我們使用CockroachDB適配器作爲元數據存儲,並使用S3適配器作爲數據存儲。還可以使用不同類型的傳輸協議,這些是Netflix Drive中即插即用接口的一部分。協議層可以是REST或gRPC。最終構成了真正的數據存儲。

image

圖8:Netflix Drive的抽象層

圖8展示了服務是如何在本地工作站和雲端進行劃分的。

工作站機器包含典型的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驅動器掛載點。工作流和設計師會對變更資產,而Netflix Drive會週期性地調用API進行快照或使用自動同步功能將這些資產上傳到雲端。

在引導過程中,Netflix Drive通常需要明確掛載點,此時需要用到用戶的認證和授權身份。該掛載點建立在本地存儲上,用來緩存文件,並作爲後端雲元數據存儲和數據存儲。清單中包含可選的預加載內容字段。

當不同類型的應用程序和工作流使用Netflix Drive時,可以根據應用程序和工作流的角色來選擇特定的運作風格。如果一個應用瞭解資產,它可能會依賴特定的REST控制接口來將文件上傳到雲端。而另一個應用在上傳文件時則無需瞭解資產,因此可能會依賴自動同步功能,在後臺上傳文件。這些是Netflix Drive爲每個角色定義的多種備選方案。

image

圖9:簡單的Netflix Drive引導清單

圖9展示了簡單的引導清單。在定義完本地存儲之後,展示了實例信息。每個掛載點可以包含多個不同的Netflix Drive實例,下面使用了兩個實例:一個動態實例和一個用戶實例,每個實例都有不同的後端數據存儲和元數據存儲。動態實例使用一個Redis元數據存儲以及一個S3數據存儲。用戶實例使用CockroachDB 作爲元數據存儲,並使用Ceph作爲數據存儲。Netflix Drive爲每個工作區分配了一個唯一標識。

image

圖10:靜態配置一個Netflix Drive命名空間

Netflix Drive的命名空間是指內部查看的所有文件。Netflix Drive可以靜態或動態創建命名空間。靜態方法(圖10)在引導時指定了需要預下載到當前實例的確切文件,爲此我們提供了一個文件會話以及一個容器信息。工作流可以在文件中預填充Netflix Drive的掛載點,這樣就可以在其之上構建後續工作流。

動態創建命名空間需要在REST接口中調用Netflix Drive APIs(圖11),這種情況下,我們會使用暫存API來暫存並從雲存儲中提取這些文件,然後將其附加到命名空間的特定位置。靜態和動態接口並不互斥。

image

圖11:動態配置Netflix Drive命名空間

更新內容

Netflix Drive上的POSIX接口可以支持open/close、move、read/write等文件操作。

部分REST API可以修改文件--例如,某個API可以暫存文件,從雲端拉取文件;某個API可以檢查文件;某個API可以保存文件,顯示地將文件上傳到雲存儲。

圖12是展示瞭如何使用Publish API將文件上傳到雲端。我們可以自動保存文件,定期檢查上傳到雲端的文件,並進行顯示保存(上傳到雲端)。顯式保存可以是不同工作流發佈時調用的API。

image

圖12:Netflix Drive發佈API

使用不同APIs的一個典型例子是:當設計師大量使用臨時數據時。由於這類數據僅僅用於過程處理,而不是最終產品,因此大部分不需要上傳到雲端。對於這類工作流,應該使用顯示保存,而非自動保存,Google Drive就是這種模式。一旦設計師確定可以將資產共享給其他設計師或工作流,此時可以調用API將其上傳到雲端。API會在設計師的Netflix Drive掛載點對所選的文件進行快照,將其上傳到雲端,並保存到特定的命名空間中。

經驗

在支持不同工作流中的多個角色使用Netflix Drive過程中,我們吸取了很多經驗。

文件、工作流、設計師工作站的性能/延遲,以及我們希望爲使用Netflix Drive的設計師提供的體驗,決定了架構的方方面面。我們使用C++實現了大部分代碼。我們對比了編程語言,發現C++的性能最佳。沒有考慮使用Rust的原因是此時Rust在FUSE文件系統的支持度還不夠成熟。

我們傾向於將Netflix Drive作爲一個通用的框架,支持任何數據存儲和元數據存儲。爲某些操作系統設計通用框架是比較困難的。在調研過可替代方案後,我們決定讓Netflix Drive支持CentOS、macOS和Windows上的FUSE文件系統。這增加了我們的測試矩陣和保障矩陣。

我們使用不同的後端,有不同的緩存層和存儲層,並依賴緩存的元數據操作。Netflix Drive支持EB級別的數據以及十億級別的資產。可擴展性是架構的另一個考量點。我們通常認爲,雲上的擴展解決方案的瓶頸是數據存儲,但最後發現元數據存儲纔是瓶頸。擴展的關鍵是處理元數據。我們重點關注元數據處理,並減少元數據存儲的調用量。通過在本地緩存大量數據可以提高工作室應用和工作流的性能,這些應用和工作流通常需要大量元數據。

我們調研了雲文件系統,如EFS,但使用文件系統無法擴展掛載點,且會影響到性能。爲了服務十億級別的資產,我們需要使用某種形式的對象存儲,而非文件存儲。這意味着設計師的文件將會被轉換爲對象(文件和對象作一對一映射)--這種方式過於簡單,但文件大小可能超過支持的最大對象大小。我們希望將一個文件映射成多個對象。如果設計師修改了文件的某個像素,Netflix Drive能夠只修改包含相關文件塊的對象。構建轉換層是權衡之下的選擇,同時這種方式也提升了擴展性。

使用對象帶來的問題是去重和分塊。對象存儲使用版本控制:每次變更對象時,無論變更大小,都會創建一個新版本對象。因此,修改文件的一個像素會導致傳送整個文件,並覆蓋原有對象。無法發送並在雲存儲中使用增量數據。通過將一個文件分爲多個對象,可以降低發送到雲端的對象大小。選擇合適的塊大小與其說是一門科學,不如說是一門藝術,因爲更小的塊意味着需要更多的數據以及轉換邏輯,並增加了元數據量。另一個需要考慮的是加密。我們需要對每個塊進行加密,因此更小的塊會導致使用更多的加密密鑰以及元數據加密。Netflix Drive的塊大小是可配置的。

多存儲層可以提升性能。當我們設計Netflix Drive時,並沒有限制僅使用本地存儲還是雲存儲。我們希望將其構建爲:可以方便地在框架中添加存儲層。該觀念貫穿整個設計、架構和代碼。例如,我們的媒體緩存僅僅是一個靠近用戶和應用的緩存層。Netflix Drive在本地文件存儲中緩存了大量數據(Google Drive則不會這麼做),因此可以較Google Drive可以更好的利用到本地文件系統的性能。

還有一個不使用AWS Storage Gateway的原因。如果多個設計師共同操作一個資產,並將每次迭代的資產都保存到雲端,這樣我們的雲開銷會爆炸。我們希望將這些資產保存到靠近用戶的媒體緩存中,並控制何時將最終拷貝發送到雲端。我們可以利用這種混合基礎設施,以及AWS Storage Gateway提供的參數。

軟件架構採用堆疊式方法至關重要。一個很好的例子是使用共享命名空間。我們目前正在開發支持不同工作站或命名空間的文件共享。我們將此構建在事件框架之上,並將其設計爲Netflix Drive架構的一部分。當一個Netflix Drive實例上的用戶向一個命名空間添加文件時,它可以生成多個雲服務可能消費的事件。然後Netflix Drive使用REST接口將文件注入訪問該命名空間的其他Netflix Drive實例中。

更多參見技術博客.

總結

本文介紹了Netflix自研的文件系統Netflix Drive。自研文件系統的一個原因是現有云服務無法滿足業務場景,如多掛載點、使用本地緩存、文件切分等。

Netflix Drive通過使用本地緩存,減少了雲存儲的開銷(如通過緩存減少了對象存儲API的調用次數)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章