介紹
通過過去三年里部署、運維Spark Streaming的積累,我們在Catalyst和DataFrames的基礎上重新架構了綽號為“Struct Streaming”的實時計算項目。
語義
我們提出來一個簡單的模型“repeated queries(RQ)”。基于該模型用戶可以從原靜態表以及SQL/DataFrames的一些概念推廣至Struct Streaming上。
工作原理:
邏輯上,每一個stream為append-only table(比如DataFrame),該表中記錄可以以任意順序到達
就像傳統的SQL/DataFrame一樣,用戶可以定義queries在整張表上,同時返回一個新的表;當到達processing time時,開始執行該queries;
用戶可以設定trigger來確定何時運行查詢以及輸出,當然,這些都是基于processing time;系統會盡快地滿足該條件(as soon as possible);
-
最終,用戶為每一個查詢設置output mode,包括如下:
- Delta: 盡管邏輯上每次查詢的結果總是一張表,但用戶可以獲取從上次trigger后的變化delet作為結果輸出;
- 這些是物理意義上的deltas,而非邏輯上的;換句話說,哪些行被增減的變化,而非對于某些行的邏輯變化;
- 用戶必須指定一個primary key(可以以組合的形式);輸出的結果中包含了一個額外的status列,該列指定該記錄是add/remove/update;
- Append: Deleta模式的一種特例,不過不包含remove的記錄;同時,不需要指定primary key,結果也不包含status列;
- Update(-in-place): 直接更新結果 (比如說update 一個mysql表),類似于Delata,primary key是必須的;
- Complete: 對于每一次查詢結果,創建一個完整的snapshot;
總之,在任意時刻每次RQ執行的結果是確定的,并且保存它的完整結果或者距離上次的變更,而每次查詢的執行則類似于Spark SQL。
- Delta: 盡管邏輯上每次查詢的結果總是一張表,但用戶可以獲取從上次trigger后的變化delet作為結果輸出;
操作
Map-only ETC job
- Query為整個表的map操作;
- Trigger為processing time(比如說1minute一次,或者越快越好);
- Output類型為Append(每次執行都會新寫入一個新的HDFS文件);
Infinite agrregation/landmark window
- Query為"select count(*) from visits group by page";
- Trigger為processing time(比如說1minute一次,或者越快越好);
- Output類型為在mysql表中的實時更新(及時更新變化的記錄);
- 針對相同的查詢,我們可以查詢已經寫入HDFS的文件,而不是再次執行然后輸出結果;
Sliding window aggregation by Event time
sliding window包含4個參數:
- 時間列;
- window的大小;
- sliding 間隔;
- window起始時間;
Tumbling window是一種特殊的sliding window,它的sliding間隔同window大小一樣;針對這種查詢,作如下處理:
- Query是一種帶有特別(多個)groupby的count操作,將所有的event map到所屬的window(類似于spark中的flatMap);
- Trigger為processing time;
- Output模型為及時替換;如果一個已經完成的window收到一個遲到的事件,我們依然可以更新老的記錄;
Query on top of window(find most popular window in past hour)
- Query: 對之前的window counted查詢添加一個top k操作;
- Trigger為processing time;
- Output模型為HDFS中的一個可更新文件或者可以寫入top k的Kafka stream(Compeleted模式)
Session statistics(count number and average length of sessions)
- Query: 對每個記錄分配一個session ID(包含session start/end/session grouping key)并做聚合操作,然后可以基于該sessionID做count(*)/max(time)/min(time);
- Trigger為processing time;
- Output模型為HDFS中的一個可更新文件
Output mode
Time和Trigger
過期數據
同其他模型的比較
Repeated Query模型的好處:
- 沒有stream的概念--所有的都是table和sql 查詢;
- 不同于Google Dataflow, triggers和outputs同查詢本身是獨立的;Dataflow中window(從sql的角度看就是一個groupby)必須確定一個outputmode 和trigger,而在RQ中,可以使用這些查詢,而不一定使用window的概念;
- 同batch processing兼容性很好;
- 許多心儀的features(sessions/feedback loops等)很容易實現;
RQ主要的缺點為查詢的漸增是由planner完成的,planner必須支持queries/output mode/triggers的結合,比如說必須支持什么時候可以刪除老的數據或者狀態,用戶對此則沒法控制。
同Storm的比較
- Storm暴露lower level api,需要用戶自己設計low level的數據流拓撲;
- Storm為單調、不可變(processing)的時間度量,不容易處理event time,同時很難處理有狀態的操作及容錯等;
同Dstream的比較
- 同Storm類似,它也暴露的為一個單調、不可變的(processing)時間度量,很難支持event time;
- API綁定在micro-batch執行模型中,這導致變化性較差,batch間隔的變化會導致整個window大小的變化;
RQ相較于以上兩種的優勢在于:
- RQ同時支持processing time和event time;
- RQ API同底層執行模型是解耦的,可以實現不基于microbatch的執行模型;
- RQ 可以提供關系型數據庫的查詢優化同時能夠處理更加復雜的查詢語句;
CQL(Streams + Tables)
CQL,Calcite和其他的一些streaming DB也有streams和table的概念, 但這些都是嘉定一個單調、不可變的時間度量,對于這些系統,結果一旦差生就不可再變更。
參考:
- Structured Streaming (aka Streaming DataFrames): https://issues.apache.org/jira/browse/SPARK-8360