概述
產生背景
在開源大數據領域,交互式引擎並不是從一開始就出現的。起初,大數據領域數據處理引擎以MapReduce爲主,但MapReduce引擎採用了批處理的理念,數據處理能力低效:
- IO密集型:Map階段中間結果寫磁盤,Reduce階段寫HDFS,多個MapReduce作業之間通過共享存儲系統HDFS交換數據。
- 任務調度和啓動開銷大,大量任務需要分佈式調度到各個節點上,且每個任務需啓動一個Java虛擬機運行。
- 無法充分利用內存,MapReduce是十多年前提出的分佈式技術,當時內存價格昂貴,所以設計的理念是充分使用磁盤,而如今內存的價格越來越便宜,新型計算引擎可以嘗試通過內存加速。
- Map端和Reduce端均需要排序:這是MapReduce設計理念決定的,使得MapReduce無法很好的應對交互式處理場景。
爲了克服MapReduce的性能缺點,Google提出了新型交互式計算引擎Dremel,它構建於Google的GFS等系統之上,支撐了Google的數據分析服務BigQuery等諸多服務。Dremel的技術兩點主要有兩個:一是採用了MPP架構,使用了多層查詢樹,使得任務可以在數千個節點上並行執行和聚合結果;二是實現了嵌套型數據的列存儲,避免了讀取不必要的數據,大大減少網絡和磁盤IO。
受Google Dremel的啓發,Cloudera等公司開發了Impala、Facebook開發了Presto,並將之開源。
交互式查詢引擎的分類
交互式查詢引擎常用語OLAP場景,根據存儲數據方式的不同可以分爲ROLAP、MOLAP和HOLAP:
- ROLAP:基於關係數據庫OLAP實現(Relational OLAP),它以關係數據庫爲核心,以關係型結構進行多維數據的表示和存儲。它將多維結構劃分成兩類表:一類是事實表,迎來存儲數據和維度關鍵字;另一類是維度表,即對每個維度至少使用一個表來存放維度層次、成員類別等維度描述信息。ROLAP的最大好處是可以實時地從源數據中獲得最新數據更新,以保持數據實時性,缺點在於運算效率比較低,用戶等待時間比較長。
- MOLAP:基於多維數據組織的OLAP實現(Multidimensional OLAP),它以多維數據組織方式爲核心,使用多維數組存儲數據。多維數據在存儲系統中形成“數據立方體(Cube)”結構,此結構是高度優化的,可以最大程度提高查詢性能。MOLAP的有事在於藉助數據多位預處理顯著提高運算效率,主要缺陷在於佔用存儲空間大和數據更新有一定延遲。
- HOLAP:基於混合數據組織的OLAP實現(Hybrid OLAP),用戶可以根據自己的業務需求,選擇哪些模型採用ROLAP、哪些採用MOLAP。一般來說,將不常用或需要靈活定義的分析使用ROLAP,而常用、常規模型採用MOLAP實現。
常見的開源實現
在大數據生態圈中,主流的應用於ROLAP場景的交互式計算引擎包括Impala和Presto,它們的特點如下:
- Hadoop Native:跟Hadoop生態系統有完好的結合。
- 計算與存儲分析:僅僅是查詢引擎,不提供數據存儲服務,所有要處理的數據都存儲在第三方系統中,比如Hive、HDFS和HBase等。
- MPP架構:採用經典的MPP架構,具有良好的擴展性,能夠應對TB甚至PB級數據的交互式查詢需求。
- 嵌套式數據存儲:支持常見的列式存儲格式,比如ORC和Parquet等。
ROLAP
Impala
Impala最初由Cloudera公司開發,設計的動機是充分結合傳統數據庫與大數據系統Hadoop的有事,構造一個全新的、支持SQL與多租戶、並具備良好的靈活性和擴展性的高性能查詢引擎。傳統數據庫與大數據系統Hadoop各有優缺點:
- 傳統關係型數據庫對SQL這種最主流的數據分析語言有完好的支持,且支持多租戶,能很好的應對高併發場景,但靈活性和擴展性較差。
- 大數據系統Hadoop具備很好的靈活性(支持各種數據存儲格式、各種存儲系統等)和擴展性(數據規模和計算規模均可以現行擴展),但對SQL及併發的支持較弱。
Cloudera結合傳統數據庫與大數據系統Hadoop各自有點,利用C++構造了一個全新的高性能查詢引擎Impala。在Cloudera的測試中,Impala的查詢效率比Hadoop生態系統中的SQL引擎Hive有數量級的提升。從技術角度上來看,Impala之所以能有好的性能,主要有以下幾方面的原因: - Impala完全拋棄了MapReduce這個不太適合做SQL查詢的範式,而是像Dremel一樣借鑑了MPP並行數據庫的思想,採用了全服務進程的設計架構,所有計算均在預先啓動的一組服務中進行,可支持更好的併發,同時省掉不必要的shuffle、sort等開銷。
- Impala採用全內存實現,不需要把中間結果寫入磁盤,省掉了大量I/O的開銷。
- 充分利用本地讀,儘可能地將數據和計算分配在同一臺機器,減少了網絡開銷。
- 用C++實現,做了很多針對底層硬件的優化,例如使用SSE指令。
Impala的基本架構採用了對等式架構,所有角色之間是對等的,沒有主從之分。如下圖所示,由三類服務組件構成,分別爲Catalogd、Statestored和Impalad,接下來依次介紹這幾個組件。
- Catalogd:元信息管理服務。它從hive metastore中同步表信息,並將任何元信息的改變通過catalogd廣播給各個Impalad服務。需要注意的是,在一個大型數據倉庫中,元數據一般很大,不同數據表的訪問頻度不同,爲此,Catalogd僅僅載入每張表的概略信息,更爲詳細的信息將由後臺進程從第三方存儲中延遲載入。
- Statestored:狀態管理服務器。元數據訂閱-發佈服務,它是單一實例(存放單點故障問題),將集羣元數據傳播到所有的Impalad進程。MPP數據庫設計的一大挑戰是實現節點間協調和元數據同步,Impala對稱的節點架構要求所有的節點必須都能夠接收並執行查詢,因此所有節點必須有系統目錄結構的最新版本和集羣成員關係的當前視圖,而Statestored正是負責以上這些功能,即將所有元信息及其修改同步到各個Impalad。
- Impalad,同時承擔協調者和執行者雙重角色。首先,對於某一查詢,作爲協調者,接收客戶端查詢請求並對其進行詞法分析、語法分析、生成邏輯查詢計劃以及物理查詢計劃,之後將各個執行片段調度到Impalad上執行;其次,接收從其他Impalad發過來的單個執行片段,利用本地資源(CPU、內存等)處理這些片段,並進一步將查詢結果返回給協調者。Impalad一般部署在及羣衆運行Datanode進程的所有機器上,進而利用數據本地化的特點而不必通過網絡傳輸,即可在文件系統中讀取數據塊。
Impala前端負責將SQL編譯爲可執行的查詢計劃,它由SQL解析器、基於成本的優化器組成。它的查詢編譯階段遵循經典的實現方式:分爲查詢解析、語義分析、查詢計劃/優化等幾個模塊。最大挑戰來自查詢計劃器,它將執行計劃分爲兩個階段: - 第一階段:將解析樹轉換爲單點計劃樹,這包括如下內容:HDFS/HBase掃描、hashjoin、crossjoin、union、hash聚集、sort、top-n和分析評估等。它基於分析評估結果,進行謂詞下推、相關列投影、分區剪枝、設置限制並完成一些基於成本的優化比如排序、合併分析窗口函數和join重排序等。
- 第二階段:將單個節點的計劃轉換爲分佈式的執行計劃,基本目標在於最小化數據移動和最大化本地數據掃描,它通過在計劃節點間增加必要的交換節點實現分佈式,通過增加額外的費交換節點最小化網絡間的數據移動,在此階段,生成物理的join策略。Impala支持兩種分佈式join放肆,表廣播(broadcast)和哈希重分佈(partittioned):表廣播方式保持一個表的數據不動,將另一個表廣播到所有相關節點;哈希重分佈的原理是根據join字段哈希值重新分佈兩張表數據。
Impala定位是爲用戶提供一套能與商業智能場景結合的查詢引擎,它與其他查詢引擎類似,支持多種商業標準:通過JDBC/ODBC訪問,通過Kerberos或LADP進行認證,遵循標準SQL的角色授權等。爲了更好地與Hive Metastore結合,它支持絕大部分HQL語法。Impala支持幾乎所有主流的數據存儲格式,包括文本格式、SequenceFile、RCFile以及Parquent等。但需要注意的是,Impala目前不支持ORCFile。
Presto
Presto是Facebook開源的交互式計算引擎,能夠處理TB級數據量。由於Presto能夠與Hive無縫集成,因此已經成爲了非常主流的OLAP引擎。
Presto查詢引擎是一個Master-Slave的架構,由一個Coordinator服務,一個Discovery Server服務,多個Worker服務組成,它們的職責如下:
- Coordinator:協調者,接收客戶端查詢請求SQL,將各個任務調度到各個Worker上執行,並在Worker返回結果之後對其進一步彙總。在一個Presto及羣衆,可以同時存在多個Coordinator,以防止單點故障。
- Discovery Server:服務發現組件,各個Worker啓動時會向Discovery Server註冊,並將狀態信息定期彙報給Discovery Server,這樣,Coordinator可隨時從Discovery Server中獲取活躍的Worker列表。Discovery Server是一個輕量級的服務,通常內嵌於Coordinator節點中。
- Worker:任務執行者,接收來自Coordinator任務,利用多線程方式並行執行,並將結果發送給Coordinator。
Presto是一個分佈式查詢引擎,並不提供數據的存儲服務。爲此,Presto採用了插件化設計思路,支持多種數據源,包括Hive、HDFS、MySQL、HBase、Redis等。Presto架構如下:
Presto是插件式架構,通過連接器接入外部數據源。爲了區分各個數據源中的數據,它在數據庫之上又引入了一層命名空間:catalog,前面提到的Hive、Cassandra和MySQL等在Presto中均以catalog方式存在。不同的catalog中可以有多個數據庫,每個數據庫中進一步可以同時存在多張數據表。
Impala與Presto的對比
MOLAP
MOLAP是一種通過預計算cube方式加速查詢的OLAP引擎,它的核心思想是“空間換時間”,典型的代表包括Druid和Kylin。
Druid
Druid是一個用於大數據實時查詢和分析的高容錯、高性能開源分佈式OLAP系統,旨在快速處理大規模數據,並能夠實現快速查詢和分析。
Druid是基於列存儲的,其設計之初主要目的是存儲時間序列數據,因此數據強制按照時間分割成不同的數據段。除了時間戳以外,一個數據段中還有維度和度量兩種類型的列。Driud能夠快速對數據進行過濾和聚合,它常用來給一些面向分析人員的應用提供查詢引擎。有些大規模的Druid集羣每秒鐘能夠插入數十億條事件並提供上千次的查詢。
Druid整個架構由實時線和批處理線兩部分構成,本質上是對Lambda架構的一種實現。Druid系統主要有三個外部依賴:用於分佈式協調的ZooKeeper;存儲集羣數據信息和相關規則的Metadata Storage;存放備份數據的Deep Storage。Druid節點類型比較多,可以從三個方面瞭解系統架構:首先從外部看,提供查詢接口的節點是Broker節點,它根據具體的情況可能會將查詢分發到實時節點或者歷史節點,前者存放實時數據,後者存放歷史數據;其次,從集羣內部看,負責協調數據存儲的是Coordinator節點,它讀取Metadata,通過ZooKeeper通知不同的Historical節點應當載入或者丟棄哪些數據段;最後,從數據Ingest來看,可以將實時數據交給Real-time節點進行處理,也可以直接將數據建好索引放到Deep Storage中,然後更新Metadata,現在Druid提倡用Indexing Service來統一處理兩種數據Ingest的情況。
Kylin
Kylin是Hadoop生態圈下的一個MOLAP系統,是ebay大數據部門從2014年開始研發的支持TB到PB級別數據量的分佈式OLAP引擎。其特點包括:
- 可擴展的超快OLAP引擎。
- 提供ANSI-SQL接口。
- 交互式查詢能力。
- 引入MOLAP Cube的概念以加速數據分析過程。
- 支持JDBC/RESTful等訪問方式,與BI工具可無縫整合。
Kylin的核心思想是利用空間換時間,通過預計算,將查詢結果預先存儲到HBase上,以加快數據的處理效率。如下圖所示: