1. 程式人生 > >Facebook資料倉庫揭祕:RCFile高效儲存結構

Facebook資料倉庫揭祕:RCFile高效儲存結構

Facebook曾在2010 ICDE(IEEE International Conference on Data Engineering)會議上介紹了資料倉庫Hive。Hive儲存海量資料在Hadoop系統中,提供了一套類資料庫的資料儲存和處理機制。它採用類SQL語言對資料進行自動化管理和處理,經過語句解析和轉換,最終生成基於Hadoop的MapReduce任務,通過執行這些任務完成資料處理。圖1顯示了Hive資料倉庫的系統結構。 

圖1 Hive資料倉庫的系統結構

基於MapReduce的資料倉庫在超大規模資料分析中扮演了重要角色,對於典型的Web服務供應商,這些分析有助於它們快速理解動態的使用者行為及變化的使用者需求。資料儲存結構是影響資料倉庫效能的關鍵因素之一。Hadoop系統中常用的檔案儲存格式有支援文字的TextFile和支援二進位制的SequenceFile等,它們都屬於行儲存方式。Facebook工程師發表的RCFile: A Fast and Spaceefficient Data Placement Structure in MapReducebased Warehouse Systems一文,介紹了一種高效的資料儲存結構——RCFile(Record Columnar File),並將其應用於Facebook的資料倉庫Hive中。與傳統資料庫的資料儲存結構相比,RCFile更有效地滿足了基於MapReduce的資料倉庫的四個關鍵需求,即Fast data loading、Fast query processing、Highly efficient storage space utilization和Strong adaptivity to highly dynamic workload patterns。

資料倉庫的需求

基於Facebook系統特徵和使用者資料的分析,在MapReduce計算環境下,資料倉庫對於資料儲存結構有四個關鍵需求。

Fast data loading

對於Facebook的產品資料倉庫而言,快速載入資料(寫資料)是非常關鍵的。每天大約有超過20TB的資料上傳到Facebook的資料倉庫,由於資料載入期間網路和磁碟流量會干擾正常的查詢執行,因此縮短資料載入時間是非常必要的。

Fast query processing

為了滿足實時性的網站請求和支援高併發使用者提交查詢的大量讀負載,查詢響應時間是非常關鍵的,這要求底層儲存結構能夠隨著查詢數量的增加而保持高速的查詢處理。

Highly efficient storage space utilization

高速增長的使用者活動總是需要可擴充套件的儲存容量和計算能力,有限的磁碟空間需要合理管理海量資料的儲存。實際上,該問題的解決方案就是最大化磁碟空間利用率。

Strong adaptivity to highly dynamic workload patterns

同一份資料集會供給不同應用的使用者,通過各種方式來分析。某些資料分析是例行過程,按照某種固定模式週期性執行;而另一些則是從中間平臺發起的查詢。大多數負載不遵循任何規則模式,這需要底層系統在儲存空間有限的前提下,對資料處理中不可預知的動態資料具備高度的適應性,而不是專注於某種特殊的負載模式。

MapReduce儲存策略

要想設計並實現一種基於MapReduce資料倉庫的高效資料儲存結構,關鍵挑戰是在MapReduce計算環境中滿足上述四個需求。在傳統資料庫系統中,三種資料儲存結構被廣泛研究,分別是行儲存結構、列儲存結構和PAX混合儲存結構。上面這三種結構都有其自身特點,不過簡單移植這些資料庫導向的儲存結構到基於MapReduce的資料倉庫系統並不能很好地滿足所有需求。

行儲存

如圖2所示,基於Hadoop系統行儲存結構的優點在於快速資料載入和動態負載的高適應能力,這是因為行儲存保證了相同記錄的所有域都在同一個叢集節點,即同一個HDFS塊。不過,行儲存的缺點也是顯而易見的,例如它不能支援快速查詢處理,因為當查詢僅僅針對多列表中的少數幾列時,它不能跳過不必要的列讀取;此外,由於混合著不同資料值的列,行儲存不易獲得一個極高的壓縮比,即空間利用率不易大幅提高。儘管通過熵編碼和利用列相關效能夠獲得一個較好的壓縮比,但是複雜資料儲存實現會導致解壓開銷增大。 

圖2 HDFS塊內行儲存的例子

列儲存

圖3顯示了在HDFS上按照列組儲存表格的例子。在這個例子中,列A和列B儲存在同一列組,而列C和列D分別儲存在單獨的列組。查詢時列儲存能夠避免讀不必要的列,並且壓縮一個列中的相似資料能夠達到較高的壓縮比。然而,由於元組重構的較高開銷,它並不能提供基於Hadoop系統的快速查詢處理。列儲存不能保證同一記錄的所有域都儲存在同一叢集節點,例如圖2的例子中,記錄的4個域儲存在位於不同節點的3個HDFS塊中。因此,記錄的重構將導致通過叢集節點網路的大量資料傳輸。儘管預先分組後,多個列在一起能夠減少開銷,但是對於高度動態的負載模式,它並不具備很好的適應性。除非所有列組根據可能的查詢預先建立,否則對於一個查詢需要一個不可預知的列組合,一個記錄的重構或許需要2個或多個列組。再者由於多個組之間的列交疊,列組可能會建立多餘的列資料儲存,這導致儲存利用率的降低。 

圖3 HDFS塊內列儲存的例子

PAX混合儲存

PAX儲存模型(用於Data Morphing儲存技術)使用混合儲存方式,目的在於提升CPU Cache效能。對於記錄中來自不同列的多個域,PAX將它們放在一個磁碟頁中。在每個磁碟頁中,PAX使用一個迷你頁來儲存屬於每個列的所有域,並使用一個頁頭來儲存迷你頁的指標。類似於行儲存,PAX對多種動態查詢有很強的適應能力。然而,它並不能滿足大型分散式系統對於高儲存空間利用率和快速查詢處理的需求,原因在於:首先,PAX沒有資料壓縮的相關工作,這部分與Cache優化關係不大,但對於大規模資料處理系統是非常關鍵的,它提供了列維度資料壓縮的可能性;其次,PAX不能提升I/O效能,因為它不能改變實際的頁內容,該限制使得大規模資料掃描時不易實現快速查詢處理;再次,PAX用固定的頁作為資料組織的基本單位,按照這個大小,在海量資料處理系統中,PAX將不會有效儲存不同大小型別的資料域。本文介紹的是RCF i l e 資料儲存結構在Hadoop系統上的實現。該結構強調:第一,RCFile儲存的表是水平劃分的,分為多個行組, 每個行組再被垂直劃分, 以便每列單獨儲存;第二,RCFile在每個行組中利用一個列維度的資料壓縮,並提供一種Lazy解壓(decompression)技術來在查詢執行時避免不必要的列解壓;第三,RCFile支援彈性的行組大小,行組大小需要權衡資料壓縮效能和查詢效能兩方面。

RCFile的設計與實現

RCFile(Record Columnar File)儲存結構遵循的是“先水平劃分,再垂直劃分”的設計理念,這個想法來源於PAX。它結合了行儲存和列儲存的優點:首先,RCFile保證同一行的資料位於同一節點,因此元組重構的開銷很低;其次,像列儲存一樣,RCFile能夠利用列維度的資料壓縮,並且能跳過不必要的列讀取。圖4是一個HDFS塊內RCFile方式儲存的例子。 

圖4 HDFS塊內RCFile方式儲存的例子

資料格式

RCFile在HDFS分散式檔案系統之上設計並實現,如圖4所示,RCFile按照下面的資料格式來儲存一張表。

RCFile基於HDFS架構,表格佔用多個HDFS塊。

每個HDFS塊中,RCFile以行組為基本單位來組織記錄。也就是說,儲存在一個HDFS塊中的所有記錄被劃分為多個行組。對於一張表,所有行組大小都相同。一個HDFS塊會有一個或多個行組。

一個行組包括三個部分。第一部分是行組頭部的同步標識,主要用於分隔HDFS塊中的兩個連續行組;第二部分是行組的元資料頭部,用於儲存行組單元的資訊,包括行組中的記錄數、每個列的位元組數、列中每個域的位元組數;第三部分是表格資料段,即實際的列儲存資料。在該部分中,同一列的所有域順序儲存。從圖4可以看出,首先儲存了列A的所有域,然後儲存列B的所有域等。

壓縮方式

RCFile的每個行組中,元資料頭部和表格資料段分別進行壓縮。

對於所有元資料頭部,RCFile使用RLE(Run Length Encoding)演算法來壓縮資料。由於同一列中所有域的長度值都順序儲存在該部分,RLE演算法能夠找到重複值的長序列,尤其對於固定的域長度。

表格資料段不會作為整個單元來壓縮;相反每個列被獨立壓縮,使用Gzip壓縮演算法。RCFile使用重量級的Gzip壓縮演算法,是為了獲得較好的壓縮比,而不使用RLE演算法的原因在於此時列資料非排序。此外,由於Lazy壓縮策略,當處理一個行組時,RCFile不需要解壓所有列。因此,相對較高的Gzip解壓開銷可以減少。

儘管RCFile對錶格資料的所有列使用同樣的壓縮演算法,不過如果使用不同的演算法來壓縮不同列或許效果會更好。RCFile將來的工作之一可能就是根據每列的資料型別和資料分佈來自適應選擇最好的壓縮演算法。

資料追加

RCFile不支援任意方式的資料寫操作,僅提供一種追加介面,這是因為底層的HDFS當前僅僅支援資料追加寫檔案尾部。資料追加方法描述如下。

RCFile為每列建立並維護一個記憶體column holder,當記錄追加時,所有域被分發,每個域追加到其對應的column holder。此外,RCFile在元資料頭部中記錄每個域對應的元資料。

RCFile提供兩個引數來控制在刷寫到磁碟之前,記憶體中快取多少個記錄。一個引數是記錄數的限制,另一個是記憶體快取的大小限制。

RCFile首先壓縮元資料頭部並寫到磁碟,然後分別壓縮每個column holder,並將壓縮後的column holder刷寫到底層檔案系統中的一個行組中。

資料讀取和Lazy解壓

在MapReduce框架中,mapper將順序處理HDFS塊中的每個行組。當處理一個行組時,RCFile無需全部讀取行組的全部內容到記憶體。

相反,它僅僅讀元資料頭部和給定查詢需要的列。因此,它可以跳過不必要的列以獲得列儲存的I/O優勢。例如,表tbl(c1, c2, c3, c4)有4個列,做一次查詢“SELECT c1 FROM tbl WHERE c4 = 1”,對每個行組,RCFile僅僅讀取c1和c4列的內容。在元資料頭部和需要的列資料載入到記憶體中後,它們需要解壓。元資料頭部總會解壓並在記憶體中維護直到RCFile處理下一個行組。然而,RCFile不會解壓所有載入的列,相反,它使用一種Lazy解壓技術。

Lazy解壓意味著列將不會在記憶體解壓,直到RCFile決定列中資料真正對查詢執行有用。由於查詢使用各種WHERE條件,Lazy解壓非常有用。如果一個WHERE條件不能被行組中的所有記錄滿足,那麼RCFile將不會解壓WHERE條件中不滿足的列。例如,在上述查詢中,所有行組中的列c4都解壓了。然而,對於一個行組,如果列c4中沒有值為1的域,那麼就無需解壓列c1。

行組大小

I/O效能是RCFile關注的重點,因此RCFile需要行組夠大並且大小可變。行組大小和下面幾個因素相關。

行組大的話,資料壓縮效率會比行組小時更有效。根據對Facebook日常應用的觀察,當行組大小達到一個閾值後,增加行組大小並不能進一步增加Gzip演算法下的壓縮比。

行組變大能夠提升資料壓縮效率並減少儲存量。因此,如果對縮減儲存空間方面有強烈需求,則不建議選擇使用小行組。需要注意的是,當行組的大小超過4MB,資料的壓縮比將趨於一致。

儘管行組變大有助於減少表格的儲存規模,但是可能會損害資料的讀效能,因為這樣減少了Lazy解壓帶來的效能提升。而且行組變大會佔用更多的記憶體,這會影響併發執行的其他MapReduce作業。考慮到儲存空間和查詢效率兩個方面,Facebook選擇4MB作為預設的行組大小,當然也允許使用者自行選擇引數進行配置。

小結

本文簡單介紹了RCFile儲存結構,其廣泛應用於Facebook公司的資料分析系統Hive中。首先,RCFile具備相當於行儲存的資料載入速度和負載適應能力;其次,RCFile的讀優化可以在掃描表格時避免不必要的列讀取,測試顯示在多數情況下,它比其他結構擁有更好的效能;再次,RCFile使用列維度的壓縮,因此能夠有效提升儲存空間利用率。

為了提高儲存空間利用率,Facebook各產品線應用產生的資料從2010年起均採用RCFile結構儲存,按行儲存(SequenceFile/TextFile)結構儲存的資料集也轉存為RCFile格式。此外,Yahoo公司也在Pig資料分析系統中集成了RCFile,RCFile正在用於另一個基於Hadoop的資料管理系統Howl(http://wiki.apache.org/pig/Howl)。而且,根據Hive開發社群的交流,RCFile也成功整合加入其他基於MapReduce的資料分析平臺。有理由相信,作為資料儲存標準的RCFile,將繼續在MapReduce環境下的大規模資料分析中扮演重要角色。