PINGO是一個由百度大數據部與百度美國研發中心合作而成的分布式交換查詢平臺。在PINGO之前,百度的大數據查詢作業主要由基於Hive的百度QueryEngine去完成。QueryEngine很好的支持著百度的離線計算任務,可是它對交互式的在線計算任務支持並不好。為了更好的支持交互式任務,我們在大約一年前設計了基於SparkSQL與Tachyon的PINGO的雛形。在過去一年中, 通過跟不同業務的結合,PINGO逐漸的演變成一套成熟高效的交互式查詢系統。本文將詳細介紹PINGO的架構迭代過程以及性能評估。
QueryEngine是基於Hive的百度內部的大數據查詢平臺,這套系統在過去幾年中較好的支撐了百度的相關業務。 圖1展示了QueryEngine的架構圖,其服務入口叫做Magi。用戶向Magi提交查詢請求, Magi為這次請求分配一個執行機, 執行機會調用Hive讀取Meta信息並向Hadoop隊列提交任務. 在這一過程中, 用戶需要自行提供計算需要的隊列資源。隨著近幾年對大數據平臺的要求越來越高, 我們在使用QueryEngine過程中也發現了一些問題:首先QueryEngine需要由用戶提供計算資源, 這使得數據倉庫的用戶需要去了解Hadoop以及相關的管理流程, 這增加了用戶使用數據的門檻。 第二, 對於很多小型計算任務而言, MR的任務的起動時間也較長, 往往用戶的計算任務只需要1分鐘, 但是排隊/提交任務就需要超過一分鐘甚至更長的時間。這樣的結果是,QueryEngine雖然很好的支持線下執行時間長的任務,但是對線上的一些交換式查詢任務(要求延時在一到兩分鐘內)確是無能為力。
為了解決這些問題, 在大約一年前,我們嘗試在離線計算的技術棧上搭建起一套具有在線服務屬性的SQL計算服務 PINGO。如圖2所示: PINGO使用了SparkSQL為主要的執行引擎, 主要是因為Spark具有下面的特點:
在過去一年中,PINGO從一個雛形開始,通過跟不同業務的結合,逐漸的演變成一套成熟高效的系統。中間經歷過幾次的架構演變,在本章中,我們將詳細介紹PINGO的迭代過程。
PINGO初版的目標是提升性能,讓其能支持交互式查詢的任務。由於Spark是基於內存的計算引擎,相對於Hive有一定的性能優勢, 所以第一步我們選擇使用Spark SQL。為求簡單,最初的服務是搭建在Spark Standalone集群上的。我們知道, Spark在Standalone模式下是不支持資源伸縮的, 一個Spark Application在啟動的時候會根據配置獲取計算資源。 這時就算一個查詢請求只有一個Task還在運行, 該Application所佔用的所有資源都不能釋放。好在一個Spark Application可以同時運行多個Job, 每個Job都能夠』平分』其所佔用的計算資源。
基於上面的考慮, 如圖3所示,我們利用Spark的Standalone集群搭建了第一版PINGO服務. 我們的主服務節點叫做Operation Manager, 它本身也是一個Spark Driver。所有用戶的請求都會從Magi Service發送到Magi Worker, 再由Magi Worker分配給Operation Manager, 通過Operation Manager在Spark集群上執行。
通過PINGO 1.0, 我們把數據倉庫的計算引擎從Hive/MR轉變成了Spark。 不過, 單純的替換計算引擎, 也許可以把查詢的性能提升1-2倍, 但是並不會使查詢的速度有數量級上的提高. 想要從本質上提高查詢速度, 我們還需要改進存儲。對此我們設計了PINGO 1.1, 加入了以Tachyon為載體的緩存系統,並在緩存層上搭建了緩存管理系統ViewManager, 進一步提升系統性能。
很多快速的查詢系統都將Parquet之類列存儲格式和分布式KeyValue存儲引擎結合起來, 通過建立索引/物化視圖等手段加速SQL查詢的速度. 通過將部分查詢條件下推到存儲引擎, 某些SQL查詢語句甚至可以被提速至100倍以上。然而我們的數據都存儲在舊版本的Hive數據倉庫中, 文件系統被限定為HDFS, 數據格式一般為低版本的ORC File, 也有不少表是ORCFile或者文本。 因為遷移成本/數據上下遊依賴等兼容性等原因, 我們沒有辦法更改Hive數據倉庫本身的存儲。
不過根據局部性原理, 任何數據訪問都有熱點. 我們可以建立緩存系統, 在緩存系統中應用最新的文件系統和存儲格式. 通過把熱點輸入通過預加載的方式導入到緩存系統, 我們可以加速整個系統的訪問性能.為此, 我們設計了以下的系統架構:
圖4: PINGO 1.1 系統架構在這個架構中, 我們引入了一個新模塊 ViewManager, 該模塊負責管理緩存系統。 它的主要功能是識別熱點數據, 將數據導入到緩存系統中, 並在查詢時改變SQL的執行過程, 使得Spark從緩存而不是原始位置讀取數據。在這個架構下,當一個Query進來時,會先向OperationManager請求。當接受到請求後,OperationManager會向ViewManager查詢數據是否已經在緩存中。如果已經在緩存,數據將被直接返回給用戶, Query完成。如果數據不在緩存中,OperationManager會向底層Data Warehouse發起請求, 等數據到達時返回給用戶。同時,ViewManager也會向底層Data Warehouse發起請求, 等數據到達時建立一個Cache Entry, 這樣的話下次同樣Query進來時,就會從緩存讀數據。注意這裡我們OperationManager與ViewManager對會向底層Data Warehouse的數據讀取是兩個獨立的STREAM, 這樣保證兩者不會互相干擾。
那PINGO又是如何動態去讀取緩存中或者底層Data Warehouse的數據的呢?畢竟在Query Plan中,數據地址是寫死的。 為了能夠讓緩存對用戶透明, 我們在SparkSQL上做了一些改進, 如下圖所述
Spark中利用Catalyst框架來執行SQL語句。 對於Catalyst框架來說, 其輸入是Unresolved Logical Plan, 這可以簡單理解為SQL語句的結構化描述。 Catalyst調用Catalog來向MetaService查詢表的元數據, Catalog返回MetastoreRelation來代表Hive表, 其中含有讀取該表的所有必要信息,以便後續的解析和優化。 而在執行時, Catalyst會把MetastoreRelation轉化為HiveTableScan, 來完成對數據的讀取。
為了實現對緩存的透明利用, 我們在其中兩個地方了做了擴展。 首先我們在Catalog中為我們緩存的表返回CachableRelation來代替MetastoreRelation。 而在將LogicalPlan轉變為真正執行的PhysicalPlan時, 我們會把CachableRelation翻譯為兩種TableScan的Union, 一個針對那些被緩存住的數據, 另外一個針對那些沒有被緩存住的數據。
通過這種方式, 我們能夠做到在用戶不感知的情況下, 完成對數據倉庫存儲層的替換和優化。 目前我們做的僅僅是改變存儲的文件系統和格式, 將來也會將同樣的實現思路應用到索引和物化視圖上。
PINGO 1.1服務很好的提高了系統性能, 但是在運營了一段時間之後, 我們逐漸感覺到Spark的集群管理問題正在成為整個系統的瓶頸。這具體表現在兩個方面
我們的整個服務其實是一個Spark Application, 服務的主節點同時是Spark的Driver。 而我們知道, Spark並不以高可靠性見長, 我們在實踐中也發現把所有的計算壓力放到單個Spark Application容易導致比較嚴重的GC問題和負載問題。 而當Spark出問題需要重啟的時候, 我們的整個服務也就暫停了。
單一Spark集群的架構無法適應多機房的基礎設施。 百度內部的離線集群規模還是很大的, 機房分布在全國的多個地區。 這樣, 我們的服務能夠獲取的資源往往來自多個機房, 而多個機房的機器是不適合組成一個Spark集群的。 另外, 當集群讀取其他機房的數據時, 帶寬往往成為整個計算任務的瓶頸。
發現這些問題是好事,說明系統已經逐漸成熟,開始往怎麼更好的運維的方向發展了。 為了解決上面的問題, 我們對系統進行了進一步的迭代. 迭代後的架構如下圖所示:
在這一版架構中, 我們將PINGO的服務和調度功能獨立出來, 與真正執行計算的部分剝離。 支持了單一查詢入口PinoMaster進行調度, 多個集群Pingo Applicatoin執行計算的多集群功能。 PingoMaster同時維護多個Spark Application。 當一個Query到來時, 我們會根據集群的歸屬/存儲的位置選擇一個最優的Application執行任務。 另外, 這一版本的PINGO還支持在yarn集群上起動Application。 百度內部有自己的資源管理系統, 提供了和yarn兼容的接口. 通過遷移PINGO服務到yarn上避免了原本Standalone版本需要的很多運維工作, 並且可以通過定期重啟Application來解決Spark的可靠性問題。
為了能夠在PINGO中實現更好的調度策略, 我們也對Spark SQL進行了深度擴展。
當Pingo收到一個Query後, 我們在Master端就完成對這條Query的分析和部分優化, 並將這些信息保存到QueryContext中。 當SQL在Application端真正執行的時候, 我們從Master端而不是Meta端拿到執行所需要的信息. 這樣做的好處是可以在根據Query的內容來做出調度. 基於這個執行流程, 目前我們開發了兩個比較有效的調度策略:
根據數據的存儲位置進行調度。 因為我們在Master端就能夠知道Query所需數據的存儲位置, 所以可以選擇合適的PingoApplication來執行這條Query。
根據數據量大小進行調度. 如上文所說, 一個Spark Aplication可以支持同時運行多個Job, 但是在很多大型的Job同時運行在一個Application又會造成FullGC等穩定性問題. 我們會根據Query輸入量的大小, 為大型Query單獨啟動Application, 而讓小Query復用同一個Application。 這樣的好處是對於多數的小Query , 我們節省了起動Application的開銷, 而又避免了大Query造成的穩定性問題。
在上一章中,我們詳細介紹了PINGO架構的迭代,在本章中,我們重點看一下PINGO的性能。如圖8所示,首先我們對比了使用Hive以及使用Spark作為計算引擎的性能。 這裡的Benchmark選取的Query是百度內部交互式數據分析的典型負載, 主要是Join/Aggregate等操作, 輸入的數據量從100M到2T左右.我們可以看到, Spark相比Hive有較大的性能優勢。在比較大比較複雜的Query中, Spark取得了2到3倍的加速比。注意在這個對比中,內存資源有限,用的是64GB內存的機器,很多Spark的數據被迫落盤, 如果有更多內存,加速比會更高。
下一步我們了解一下加了緩存後的性能, 在這個實驗中,我們使用了192GB的機器,有更多的內存去支持緩存以及內存計算。如圖9所示,在這個環境下,使用Spark相對於Hive有大概5到7倍的提速。 在加入了Tachyon後,相對於Hive無緩存的情況有30到50倍的提速。我們相信在未來的幾年內,內存價格會大幅降低,內存計算會變成主流,所以使用內存做緩存是一個正確的方向。
PINGO服務目前被應用在交互式查詢場景中, 旨在為PM和RD提供快速的數據分析服務。 圖10展示了在同樣的計算資源下, 在生產環境使用PINGO前後的Query執行時間分布圖。注意,在這個生產環境中,我們用的是64GB內存的機器, 為了提供足夠的緩存空間,我們使用了Tachyon的Tiered Storage功能,讓緩存分布在內存以及本地磁碟中。 我們可以看到, 在傳統的基於Hive+MR的服務模式下, 只有1%左右的Query能夠在兩分鐘內完成. 而採用了基於Spark的PINGO服務, 有50%+的Query可以在兩分鐘內執行完成。 能夠取得這樣的加速效果, 部分原因是Spark本身的執行效率比Hive要高一些。這個本身還有很大的優化空間,比如如果我們使用內存緩存的話,執行時間可以輕易的壓縮到30秒內。
經過過去一年的迭代與發展,PINGO已經很好的支持了百度內部的交互式查詢業務。通過PINGO,很多查詢的延時從以前的30到40分鐘,降低到了2分鐘以內,很大的提高了查詢者的工作效率。今後PINGO的發展將朝著更好用,已經更快兩個方向發展。為了讓PINGO更好用,我們正在PINGO之上開發UI, 讓用戶與圖形界面交互(而不是通過輸入SQL Query)就能輕易的查詢到想要的數據。為了讓PINGO更快,更有交互性,我們希望可以把90%以上的Query 時間降低到30秒以下。第一步就是要擴大我們的Cache的覆蓋率與性能,設計出更好的緩存預取以及緩存替換機制,並且加速Cache讀取的延時。第二步,我們也通過硬體加速的方法使用FPGA加速某些常用的SQL Operator。就在最近,我們對SQL的JOIN Operator進行了FPGA硬體加速,相對CPU取得了3倍的加速比。我們也會很快把這項技術使用到PINGO上。
作者簡介:
溫翔,百度公司大數據部資深工程師。北京大學計算機本科以及碩士研究生畢業。曾在騰訊公司從事大數據平臺開發。目前主要從事百度大數據交換式查詢平臺架構以及開發。
沈光昊,百度公司大數據部主任架構師。浙江大學計算機碩士。曾在Facebook工作。目前主要負責百度大數據部的總體架構。
蔡旻諧,百度美國研發中心研發架構師。臺灣大學畢業,加州大學洛杉磯分校(UCLA)計算機碩士,曾任職於雅虎微軟從事搜索廣告平臺核心設計研發。目前任職於百度美研基礎架構部,主要從事分布式計算平臺Spark與深度學習平臺的研發設計工作。
徐寶強,百度公司大數據部高級項目經理。牛津大學計算機碩士。目前主要從事大數據平臺項目管理工作。
劉少山,百度公司美國研發中心高級架構師。加州大學歐文分校計算機博士。曾在LinkedIn, Microsoft, Microsoft Research, INRIA, Intel以及Broadcom工作。目前主要從事百度深度學習, 大數據,以及異構計算平臺架構與開發。
責編:錢曙光,關注架構和算法領域,尋求報導或者投稿請發郵件qianshg@csdn.net,另有「CSDN 高級架構師群」,內有諸多知名網際網路公司的大牛架構師,歡迎架構師加微信qshuguang2008申請入群,備註姓名+公司+職位。
版權聲明:本文為《程式設計師》原創文章,未經允許不得轉載,訂閱2016年程式設計師請訪問 http://dingyue.programmer.com.cn
想了解IT產品研發背後的那些人、技術和故事,請關注CSDN(資訊)微信公眾號:CSDNnews