為媒體資產構建一個雲原生的檔案系統

charlieroro發表於2022-06-14

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的呼叫次數)。

相關文章