標籤:

ALLUXIO在攜程大數據平台中的應用與實踐

進入大數據時代,實時作業有著越來越重要的地位,並且部分實時和離線作業存在數據共享。實踐中使用統一的資源調度平台能夠減少運維工作,但同時也會帶來一些問題。

本文將介紹攜程大數據平台是如何引入Alluxio來解決HDFS停機維護影響實時作業的問題,並在保證實時作業不中斷的同時,減少對HDFSNameNode的壓力,以及加快部分Spark SQL作業的處理效率。

背景

攜程作為中國旅遊業的龍頭,早在2003年就在美國上市,發展到現在,攜程對外提供酒店、機票、火車票、度假、旅遊等線上服務產品, 每天線上有上億的訪問量,與此同時,海量的用戶和訪問也產生了大量的數據,這些數據包括日誌以及訪問記錄,這些數據都需要落地到大數據平台上。

為了對這些數據進行分析, 我們在大數據方面有著大量的離線和實時作業。主集群已突破千台的規模, 有著超過50PB的數據量,每日的增量大概在400TB。巨大的數據量且每天的作業數達到了30萬,給存儲和計算帶來了很大的挑戰。

HDFS NameNode在存儲大量數據的同時,文件數和block數給單點的NameNode處理能力帶來了壓力。因為數據存在共享,所以只能使用一套HDFS來存儲數據,實時落地的數據也必須寫入HDFS。

為了緩解和優化NameNode的壓力,我們會對NameNode進行源碼優化,並進行停機維護。而HDFS的停機會導致大量的需要數據落地到HDFS的Spark Streaming作業出錯,對那些實時性要求比較高的作業,比如實時推薦系統,這種影響是需要極力避免的。

圖1 攜程大數據平台架構圖

圖1為攜程大數據平台架構圖,DataSource為不同的數據源,有日誌信息、訂單信息。它們通過攜程自己研發的中間件或者直接落地到HDFS或者被Spark Streaming消費之後再落地到HDFS。

Streaming計算的結果有的直接落地到Redis或者ElasticSearch等快速查詢平台,而有些Streaming計算的實時數據需要和歷史數據進行再計算,則需要落地到HDFS上。

按照業務層不同的需求,我們提供了不同的執行引擎來對HDFS上的數據進行計算。執行快速的Spark SQL和Kylin主要用在OLAP上,Hive和Spark SQL同時用在ETL作業上,Presto主要用在adhoc查詢。

上述架構能夠滿足大部分的工作要求,但是隨著集群規模的增大,業務作業的增多,集群面臨了很大的挑戰,其中也存在著諸多不足。

上述架構存在以下幾個問題:

1. SparkStreaming依賴於HDFS,當HDFS進行停機維護的時候,將會導致大量的Streaming作業出錯。

2. SparkStreaming在不進行小文件合併的情況下會生成大量的小文件,假設Streaming的batch時間為10s,那麼使用Append方式落地到HDFS的文件數在一天能達到8640個文件,如果用戶沒有進行Repartition來進行合併文件,那麼文件數將會達到Partition*8640。我們具有接近400個Streaming作業,每天落地的文件數量達到了500萬,而目前我們集群的元數據已經達到了6.4億,雖然每天會有合併小文件的作業進行文件合併,但太大的文件增量給NameNode造成了極大的壓力。

3. SparkStreaming長時間佔用上千VCores會對高峰時期的ETL作業產生影響,同時,在高峰期如果Streaming出錯,作業重試可能會出現長時間分配不到資源的情況。

為了解決上述問題,我們為SparkStreaming搭建了一套獨立的Hadoop集群,包括獨立的HDFS、Yarn等組件。

雖然上述問題得到了很好的解決,但這個方案仍然會帶來一些問題。如果主集群想訪問實時集群中的數據時,需要用戶事先將數據DistCp到主集群,然後再進行數據分析。架構如圖2所示。除了DistCp能夠跨集群傳輸數據之外,我們第一個想到的就是Alluxio。

圖2 獨立集群架構: HDFS2獨立與主集群HDFS1以提供資源隔離

Alluxio作為全球第一個基於內存級別的文件系統,具有高效的讀寫性能,同時能夠提供統一的API來訪問不同的存儲系統。它架構在傳統分散式文件系統和分散式計算框架之間,為上層計算框架提供了內存級別的數據讀寫服務。

如圖3所示,Alluxio可以支持目前幾乎所有的主流分散式存儲系統,可以通過簡單配置或者Mount的形式將HDFS、S3等掛載到Alluxio的一個路徑下。這樣我們就可以統一的通過Alluxio提供的Schema來訪問不同存儲系統的數據,極大的方便了客戶端程序開發。

同時,對於存儲在雲端的數據或者計算與存儲分離的場景,可以通過將熱點數據load到Alluxio,然後再使用計算引擎進行計算,這極大的提高了計算的效率,而且減少了每次計算需要從遠程拉去數據的所導致的網路IO。而我們利用Alluxio統一入口的特性,掛載了兩個HDFS集群,從而實現了從Alluxio一個入口讀取兩個集群的功能,而具體訪問哪個底層集群,完全由Alluxio幫我們實現了。

圖3 Alluxio 統一存儲和抽象

解決方案

為了解決數據跨集群共享的問題,我們引入了國際知名並且開源的Alluxio。部署的Alluxio1.4 具有良好的穩定性和高效性,在引入Alluxio之後,架構如圖4所示。

圖4 改進後架構圖

從圖4可以看到,Spark Streaming數據直接落地到Alluxio,Alluxio通過將HDFS1和HDFS2分別掛載到兩個路徑下。簡單的通過命令:

$ alluxiofs mount /path/on/alluxio hdfs://namenode:port/path/on/hdfs

就能分別掛載這兩個HDFS集群。

HDFS-2集群專門負責存儲流計算的數據。數據收集到Kafka之後,Spark Streaming對其進行消費,計算後的數據直接寫掛載了HDFS-2集群的路徑。

Alluxio很友好的為Client提供了三種寫策略,分別是:MUST_CACHE、CACHE_THROUGH、THROUGH,這三種策略分別是只寫Alluxio,同步到HDFS,只寫HDFS。這裡可以根據數據的重要性,採用不同的策略來寫Alluxio,重要的數據需要同步到HDFS,允許數據丟失的可以採用只寫Alluxio策略。

採用上述策略方案之後,我們發現Alluxio在一定程度上減少了NameNode的壓力。部分熱點數據並且多次使用的數據,我們會通過定時作業將該部分數據載入到Alluxio,一方面加快了計算引擎載入數據的速度,另外一方面減少了對NameNode的數據訪問請求數。

此外, Alluxio自身實現了一個叫做TTL(Time To Live)的功能,只要對一個路徑設置了TTL,Alluxio內部會對這部分數據進行檢測,當前時間減去路徑的創建時間大於TTL數值的路徑會觸發TTL功能。

考慮到實用性,Alluxio為我們提供了Free和Delete兩種Action。Delete會將底層文件一同刪除,Free只刪Alluxio而不刪底層文件系統。為了減少Alluxio內存壓力,我們要求寫到Alluxio中的數據必須設置一個TTL,這樣Alluxio會自動將過期數據刪除(通過設置Free Action策略,可以刪除Alluxio而不刪除HDFS)。對於從Alluxio內存中載入數據的Spark Sql作業,我們拿取了線上的作業和從HDFS上讀數據進行了對比,普遍提高了30%的執行效率。

後記

從調研Alluxio到落地上線Alluxio,整個過程下來,我們碰到過一系列的問題, 針對這些問題以及業務需求, 開發了一系列的功能並回饋了Alluxio社區。

1. Alluxio在寫HDFS的時候,需要使用HDFS的Root賬號許可權,對於帶Kerberos的HDFS集群,會出現無許可權寫。為了解決這個問題,我們為Alluxio單獨建了一個Hadoop賬號,所有落地到HDFS的數據通過該賬號來寫。

2. 1.4版本的Alluxio不支持以文件夾的形式進行TTL的設置,我們進行了功能的完善並貢獻給社區(出現在1.5以及後續版本中)。

3. 1.4版本不支持TTL使用Free策略來刪除數據,我們對該功能進行了完善並貢獻給社區(出現在1.5以及後續版本中)。

4. 1.4版本底層文件發生修改,對於Alluxio來說是不感知的,而通過Alluxio讀取的數據可能出現不準確(1.7版本得到了徹底解決),我們開發了一個shell命令checkConsistency和repairConsistency來解決這個問題。

【作者簡介】郭建華,攜程技術中心軟體研發工程師,2016年加入攜程,在大數據平台部門從事基礎框架的研究與運維,主要負責HDFS、Alluxio等離線平台的研發運維工作。

更多來自攜程技術人的一手乾貨,歡迎搜索關注「攜程技術中心」微信公號。


推薦閱讀:

大數據可能「說謊」 非結構化數據將呈現更豐富的世界
怎麼才能用數據實現商業價值?
關於大數據四大方面的十五大關鍵技術詳解
從頭學習大數據培訓課程 NOSQL 資料庫 hbase(三)hbase 的 filter 用法,hbase 數據的批量導入
濰坊房價鬧哪樣,且看且珍惜

TAG:大數據 |