說說阿里增量計算框架Galaxy

wqnmbdd發表於2016-12-12

增量計算模型 (一)

背景

Galaxy是阿里資料平臺事業部,實時計算組自研的增量計算框架。今年雙十一,阿里直播大屏就是Galaxy支援和保障的重要業務之一,相信大家可能看過雙十一之後網上一些介紹性的文章了,比如 阿里研發實時計算平臺
每秒運算量將超千萬
 ,不過這篇文章面向非技術人員,最後的比喻也是有點醉。還這篇比較新的  阿里巴巴實時資料公共層助力雙11媒體直播 。

本文我會介紹一些我認為可以公開出來說的galaxy技術上的特點,讓技術人員對該計算框架有個更準確的認識。

計算模型

首先明確根本的一點, Galaxy是增量計算模型 ,不是”簡單”的流計算,這點在業界是沒有的。 增量計算是有狀態的計算 。批量計算裡,每一次的輸出結果只與本次全量掃進來的資料有關,而且計算是冪等的。增量計算,每批計算結果,是由本批資料和歷史批次結果計算出來的,即newValue
= function(currentBatchValue, oldValue),然後本批計算出來的newValue會作為oldValue參與下一批資料的計算中。這個公式看起來與迭代計算相似,實質上,迭代計算是增量計算的一種。

下面說明流計算與Galaxy的關係。

Galaxy與Storm

網上對Galaxy有過了解的技術朋友,包括阿里內部的同事,可能會認為Galaxy只是Storm上的一層封裝。在這裡,我嚴肅地告訴大家,只要你動腦子想一想, 絕對不是的 ,不但不是封裝,而且與Storm有本質區別。

Storm是流式計算,資料流進,經歷拓撲計算,資料流出,與增量模型沒有半毛錢關係。如果真要類比storm和galaxy,大家可以想一想Trident。trident是storm上的封裝,暴露介面讓使用者可以操縱state,如此,批與批之間的計算結果的確可以通過state持久化起來了,並且可以參與下一批的計算,這看上去與galaxy做的相似。但還是有一個本質區別,trident的state不是它能掌控的,說白了,你state是額外的輔助儲存,不是與我這個引擎掛鉤的,而 Galaxy中的state是與整個計算框架關聯起來的 ,這點太重要了,而且實現起來是很複雜的。

再說為什麼現在的galaxy版本需要依賴storm。galaxy目前舊的版本還是跑在storm上的,藉助storm的拓撲拉起,worker排程和訊息傳遞。galaxy只是需要一個能夠拉起worker,傳遞訊息或者作RPC的引擎而已,storm是當時一個的臨時選擇。目前,storm引擎已經不再適合galaxy,無論是其拓撲構建和拉起的耗時,還是拓撲的不可變性,或是訊息格式及序列化方面的效能等等種種問題,都不再適合galaxy,而僅僅適合於流計算。所以,將來galaxy的引擎,不會是這樣。

Galaxy的未來

簡單說幾點Galaxy的想象空間。

現今Spark可以做的場景,Galaxy都是可以做的,而且Galaxy在效能上 至少是準實時 的。Spark的RDD代表了使用上的易用性和計算上的reuse資料。Galaxy同樣有增量語義,表達能力同樣強大的運算元層和增量計算模型天然引入的資料reuse。

Galaxy的計算模型在業界是沒有的,其計算場景覆蓋了流式計算,迭代計算,還可以輕鬆愉悅地做BSP模型。

增量計算模型(二)

背景

在前一篇文章中,介紹到了Galaxy的增量計算性質,其state是框架內部管理的,以及與Storm的簡單對比。這篇文章將講述更多Galaxy增量模型的事情,並介紹這套增量模型之上實現的Galaxy SQL和Galaxy Operator,同時會從增量角度對比Spark Streaming。

Galaxy MRM增量與Spark Streaming

MRM模型全稱為MapReduceMerge,比MapReduce做了一個Merge操作。merge階段可與state互動,讀寫某個key的oldValue,並且這個merge介面還具備rollback語義。在流計算場景下,資料按時間或條數切成不同的批,批內可以做普遍意義下的MapReduce操作,批之間需要merge階段做跨批聚合的計算。大家可以對比Spark Streaming的UpdateStateByKey操作,在一個DStream內,各個時間段內的RDD(即各批)可以通過這個介面更新一次任務內的state。而galaxy的merge本質上是一次add的過程,對應的rollback是一次delete的過程,從資料庫的語義看,兩個過程合起來相當於是update操作,而這倆過程都是根據一個primary
key來做的,所以這件事情與spark streaming的updateStateByKey做的事情是一樣的,但是細看的話,兩者還是存在很大的差異。

galaxy的state暴露給計算task是執行緒級別獨享的,spark streaming的state是任務內全域性共享的。執行緒級別獨享的優點,就在於同一批資料,按key shuffle之後來到不同的merge計算節點,各自不會阻塞各自的計算過程,而spark streaming的updateStateByKey操作會阻塞其他rdd的計算,雖然spark streaming能做到DStream內各個RDD併發執行,但是隻要有state操作,最終還是落到了時間序列上的阻塞。本時間點StateRDD的計算需要依賴前一時間點父StateRDD的計算結果,而批內各個key對state操作是互相阻塞和影響的,所以著眼在這層barrier上的話,galaxy的merge過程更加精細,add和delete過程是分開的,批內的key是落到不同執行緒上計算而state是執行緒內獨享的。

Galaxy有三種Model,分別是MapOnlyModel,MapReduceModel,MapReduceMergeModel。即,你可以使用M Model和MR Model做普通的流計算或小批計算,當需要跨批操作的時候就使用MRM Model。Model之間是隨意組合串聯的,介面相比MapReduce其實是相當靈活甚至過於靈活的,靈活的弊端是計算模型上帶來複雜性。

Galaxy SQL

Galaxy SQL是一種StreamSQL,而且是目前業界沒有的。從語法上Galaxy SQL貼近HiveSQL,但又有些流計算語義上(無限資料流)不能支援的語法,比如limit, order by。

Intel那邊搞了一個Spark Streaming + Spark SQL的結合,叫StreamSQL。利用Spark SQL裡的SchemaRDD,為Spark Streaming流進來的RDD帶上了Schema元資訊。藉助Spark Streaming支援的操作,這種StreamSQL可以做滑窗效果的sql計算。但是真正跨批的增量語義(不僅僅是固定的window跨批計算),是支援不了的。Galaxy SQL可以做真正的增量流式SQL。

舉個最簡單的例子,

insert into t2 
  select t1.a as k, count(t1.b) as cnt from t1 group by t1.a;

select count(cnt) from t2 group by t2.cnt;

第一句sql中,根據t1的a欄位分組,求了個count值。第二句sql中,t2表分組的欄位變為t1表裡count出來的cnt值。大家可以想象,在流計算場景裡,第一次a求count出來的值可能是100,下一個時間點,同一個a的key,count出來的值就是200了,這時候,100這個cnt已經丟到t2表裡計算出結果了,現在100已經更新到200了,200這個新的值的計算是簡單的,但問題是如何把t2裡之前100的計算結果撤銷呢?

可以仔細想想,StreamSQL是做不了這樣的sql的,本質上是因為spark streaming不支援這樣的操作。Galaxy計算框架的merge階段可以做rollback操作,回滾之前”錯誤”的狀態,使得Galaxy SQL可以做分散式流式SQL。

Galaxy Operator

Galaxy Operator是Galaxy MRM程式設計介面之上的一層DAG封裝,兼具易用性和表達能力。

運算元層最終將對映成多個Galaxy的MRM Model,使使用者可以更加關注計算邏輯,遮蔽較複雜的MRM Model,特別是merge階段。

運算元層相當於是物理執行計劃,本身可以做節點合併、謂詞下推等優化的工作,即物理執行計劃的優化。從本質上,我認為類似Hive、Spark Catalyst裡對執行計劃的優化工作,在運算元層這個DAG裡都是可以做的。通過運算元這一層,理論上任何DSL都是可以對映之後在Galaxy計算框架上執行的。

運算元層提供五類正交的基礎運算元:map, reduce,merge,shuffle,union。五類基礎運算元可以互相組合,衍生成更高階的運算元。

需要注意的是,reduce類的運算元 ,針對的是 本批 內資料的聚合。增量語義下的reduce與批量語義下MapReduce中的reduce並不一樣,增量語義下的reduce針對的是本批,MapReduce中的reduce對應跨批的資料,更加類似增量語義下的merge。merge類的運算元 ,針對的是 跨批 的聚合操作。merge()對應的是MRM模型裡的Merge phase,可與OldValue互動,是增量場景中的特性操作。通常用於實現count、sum等UDAF操作,也可以實現top、distinct、類join的操作。

union類的運算元 ,針對的是多流合併的場景。union()操作是將多條流合併成一條流輸出,要求各流的columns對齊且一致。mix()操作也是多流合併成一條,但內部標明瞭資料來自左流還是右流,各流的column可以不一致,後續可以銜接集合性的批內或跨批操作。mix()是 專門為集合性 操作而設計的介面。

功能上,運算元層可以類比Spark RDD。Spark RDD 核心價值 有二:其一,在api層面,規避MapReduce模型的抽象和不舒適的生介面,提供多種transformations和actions,方便開發者理解和使用,即 easy to use ;其二,在計算層面,通過持久化RDD做到了批量計算過程中對中間資料的複用,使Spark誕生之初以適合迭代型計算的記憶體計算框架聞名,即 reuse
data 。反觀Galaxy運算元層,一方面,運算元層與Spark RDD一樣,在api設計上具備FlumeJava的設計理念,兼具易用性和表達能力;另一方面,Galaxy之增量計算模型是 “有狀態的計算” ,天然做到了實時資料各批之間”狀態”的reuse(在merge phase)。

後續

之後有時間,希望可以介紹下Galaxy的任務模型、對於state的管理和容錯等方面的內容。


相關文章