SparkES 多維分析引擎設計
來自: http://www.jianshu.com/p/556ac1bd29ea
設計動機
ElasticSearch 毫秒級的查詢響應時間還是很驚艷的。其優點有:
- 優秀的全文檢索能力
- 高效的列式存儲與查詢能力
- 數據分布式存儲(Shard 分片)
其列式存儲可以有效的支持高效的聚合類查詢,譬如groupBy等操作,分布式存儲則提升了處理的數據規模。
相應的也存在一些缺點:
- 缺乏優秀的SQL支持
- 缺乏水平擴展的Reduce(Merge)能力,現階段的實現局限在單機
- JSON格式的查詢語言,缺乏編程能力,難以實現非常復雜的數據加工,自定義函數(類似Hive的UDF等)
Spark 作為一個計算引擎,可以克服ES存在的這些缺點:
- 良好的SQL支持
- 強大的計算引擎,可以進行分布式Reduce
- 支持自定義編程(采用原生API或者編寫UDF等函數對SQL做增強)
所以在構建即席多維查詢系統時,Spark 可以和ES取得良好的互補效果。通過ES的列式存儲特性,我們可以非常快的過濾出數據,并且支持全文檢索,之后這些過濾后的數據從各個Shard 進入Spark,Spark分布式的進行Reduce/Merge操作,并且做一些更高層的工作,最后輸出給用戶。
通常而言,結構化的數據結構可以有效提升數據的查詢速度,但是會對數據的構建產生一定的吞吐影響。ES強大的Query能力取決于數據結構化的存儲(索引文件),為了解決這個問題,我們可以通過Spark Streaming有效的對接各個數據源(Kafka/文件系統)等,將數據規范化后批量導入到ES的各個Shard。Spark Streaming 基于以下兩點可以實現為ES快速導入數據。
- Spark RDD 的Partition 能夠良好的契合ES的Shard的概念。能夠實現一一對應。避免經過ES的二次分發
- Spark Streaming 批處理的模式 和 Lucene(ES的底層存儲引擎)的Segment對應的非常好。一次批處理意味著新生成一個文件,
我們可以有效的控制生成文件的大小,頻度等。
架構設計
下面是架構設計圖:

整個系統大概分成四個部分。分別是:
- API層
- Spark 計算引擎層
- ES 存儲層
- ES 索引構建層
API 層
API 層主要是做多查詢協議的支持,比如可以支持SQL,JSON等形態的查詢語句。并且可是做一些啟發式查詢優化。從而決定將查詢請求是直接轉發給后端的ES來完成,還是走Spark 計算引擎。也就是上圖提到的 Query Optimize,根據條件決定是否需要短路掉 Spark Compute。
Spark 計算引擎層
前面我們提到了ES的三個缺陷,而Spark 可以有效的解決這個問題。對于一個普通的SQL語句,我們可以把 where 條件的語句,部分group 等相關的語句下沉到ES引擎進行執行,之后可能匯總了較多的數據,然后放到Spark中進行合并和加工,最后轉發給用戶。相對應的,Spark 的初始的RDD 類似和Kafka的對接,每個Kafka 的partition對應RDD的一個partiton,每個ES的Shard 也對應RDD的一個partition。
ES 存儲層
ES的Shard 數量在索引構建時就需要確定,確定后無法進行更改。這樣單個索引里的Shard 會越來越大從而影響單Shard的查詢速度。但因為上層有了 Spark Compute層,所以我們可以通過添加Index的方式來擴大Shard的數目,然后查詢時查詢所有分片數據,由Spark完成數據的合并工作。
ES 索引構建層
數據的結構化必然帶來了構建的困難。所以有了Spark Streaming層作為數據的構建層。這里你有兩種選擇:
- 通過ES原生的bulk API 完成索引的構建
- 然Spark 直接對接到 ES的每個Shard,直接針對該Shard 進行索引,可有效替身索引的吞吐量。