Spark缺點
無論是
Spark Streaming
還是
Structured Streaming
,
Spark
流處理的實時性還不夠,所以無法用在一些對實時性要求很高的流處理場景中。
這是因為
Spark
的流處理是基於所謂微批處理
( Micro- batch processing)
的思想,即它把流
處理看作是批處理的一種特殊形式,每次接收到一個時間間隔的資料才會去處理,所以天生很難在實時性上有所提升。
雖然在
Spark2.3
中提出了連續處理模型
( Continuous Processing Model),
但是現在只支援
很有限的功能,並不能在大的專案中使用。
Spark
還需要做出很大的努力才能改進現有的流處理模型想要在流處理的實時性上提升,就不能継續用微批處理的模式,而要想辦法實現真正的流處理即每當有一條資料輸入就立刻處理,不做等待。
Flink
採用了基於運算子
(Operator)
的連續流模型,可以做到
微秒級別的延遲
。
Flink 核心模型簡介
Flink
最核心的資料結構是
Stream
,它代表一個執行在多分割槽上的並行流。
在
Stream
上同樣可以進行各種轉換操作
(Transformation)
。與 Spark 的 RDD 不同的是,Stream 代表一個數據流而不是靜態資料的集合。所以,它包含的資料是隨著時間增長而變化的。而且 Stream 上的轉換操作都是逐條進行的,即每當有新的資料進來,整個流程都會被執行並更新結果。這樣的基本處理模式決定了 Flink 會比 Spark Streaming 有更低的流處理延遲性。
當一個 Flink 程式被執行的時候,它會被對映為 Streaming Dataflow,下圖就是一個Streaming Dataflow 的示意圖。
在圖中,你可以看出
Streaming Dataflow
包括
Stream
和
Operator
(運算子)。轉換運算子把一個或多個
Stream
轉換成多個
Stream
。每個
Dataflow
都有一個輸入資料來源(
Source
)和輸出資料來源(
Sink
)。與Spark的RDD轉換圖類似,Streaming Dataflow也會被組合成一個有向無環圖去執行。
在
Flink
中,程式天生是並行和分散式的。一個
Stream
可以包含多個分割槽(
Stream Partitions
),一個運算子可以被分成多個運算子子任務,每一個子任務是在不同的執行緒或者不同的機器節點中獨立執行的。如下圖所示:
從上圖你可以看出,
Stream
在運算子之間傳輸資料的形式有兩種:一對一和重新分佈。
一對一(
One-to-one)
:
Stream
維護著分割槽以及元素的順序,比如上圖從輸入資料來源到
map
間。這意味著map運算子的子任務處理的資料和輸入資料來源的子任務生產的元素的資料相同。你有沒有發現,它與RDD的窄依賴類似。
重新分佈(
Redistributing
):
Stream
中資料的分割槽會發生改變,比如上圖中
map
與
keyBy
之間。運算子的每一個子任務把資料傳送到不同的目標子任務。
Flink的架構
當前版本Flink的架構如下圖所示
這個架構和
Spark
架構比較類似,都分為四層:儲存層、部署層、核心處理引擎、
high-level
的
API
和庫。
從儲存層來看,
Flink
同樣相容多種主流檔案系統如
HDFS、Amazon S3
,多種資料庫如
HBase
和多種資料流如
Kafka
和
Flume
。
從部署層來看,
Flink
不僅支援本地執行,還能在獨立叢集或者在被
YARN
或
Mesos
管理的叢集上執行,也能部署在雲端。
核心處理引擎就是我們剛才提到的分散式
Streaming Dataflow
,所有的高階
API
及應用庫都會被翻譯成包含
Stream
和
Operator
的
Dataflow
來執行。
Flink
提供的兩個核心
API
就是
DataSet APl
和
DataStream APl
。你沒看錯,名字和
Spark
的
DataSet、DataFrame
非常相似。顧名思義,
DataSet
代表有界的資料集,而
DataStream
代表流資料。所以,
DataSet API
是用來做批處理的,而
DataStream API
是做流處理的。
也許你會問,Flink 這樣基於流的模型是怎樣支援批處理的?在內部,
DataSet
其實也用
Stream
表示,靜態的有界資料也可以被看作是特殊的流資料,而且
DataSet
與
DataStream
可以無縫切換。所以,
Flink
的核心是
DataStream
。
Flink 和 Spark 對比
透過前面的學習,我們瞭解到,
Spark
和
Flink
都支援批處理和流處理,接下來讓我們對這兩種流行的資料處理框架在各方面進行對比。首先,這兩個資料處理框架有很多相同點。
都基於記憶體計算;
都有統一的批處理和流處理
APl
,都支援類似
SQL
的程式設計介面;
都支援很多相同的轉換操作,程式設計都是用類似於
Scala Collection APl
的函數語言程式設計模式;
都有完善的錯誤恢復機制;
都支援
Exactly once
的語義一致性。
當然,它們的不同點也是相當明顯,我們可以從4個不同的角度來看。
從流處理的角度來講,
Spark
基於微批次處理,把流資料看成是一個個小的批處理資料塊分別處理,所以延遲性只能做到秒級。而
Flink
基於每個事件處理,每當有新的資料輸入都會立刻處理,是真正的流式計算,支援毫秒級計算。由於相同的原因,
Spark只支援基於時間的視窗操作(處理時間或者事件時間)
,而
Flink
支援的視窗操作則非常靈活,不僅支援時間視窗,還支援基於資料本身的視窗(另外還支援基於
time
、
count
、
session
,以及
data-driven
的視窗操作),開發者可以自由定義想要的視窗操作。
從
SQL
功能的角度來講,
Spark
和
Flink
分別提供
SparkSQL
和
Table APl
提供
SQL
互動支援。兩者相比較,
Spark
對
SQL
支援更好,相應的最佳化、擴充套件和效能更好,而Flink在SQL支援方面還有很大提升空間。
從迭代計算的角度來講,
Spark
對機器學習的支援很好,因為可以在記憶體中快取中間計算結果來加速機器學習演算法的執行。但是大部分機器學習演算法其實是一個有環的資料流,在
Spark
中,卻是用無環圖來表示。而
Flink
支援在執行時間中的有環資料流,從而可以更有效的對機器學習演算法進行運算。
從相應的生態系統角度來講,Spark 的社群無疑更加活躍。
Spark
可以說有著
Apache
旗下最多的開源貢獻者,而且有很多不同的庫來用在不同場景。而
Flink
由於較新,現階段的開源社群不如
Spark
活躍,各種庫的功能也不如
Spark
全面。但是
Flink
還在不斷髮展,各種功能也在逐漸完善。
如何選擇Spark和Flink
對於以下場景,你可以選擇
Spark
。
資料量非常大而且邏輯複雜的批資料處理,並且對計算效率有較高要求(比如用大資料分析來構建推薦系統進行個性化推薦、廣告定點投放等);
基於歷史資料的互動式查詢,要求響應較快(
impala,或者presto更優秀
);
基於實時資料流的資料處理,延遲性要求在在數百毫秒到數秒之間。
Spark
完美滿足這些場景的需求,而且它可以一站式解決這些問題,無需用別的資料處理平臺。由於
Flink
是為了提升流處理而建立的平臺,所以它適用於各種需要非常低延遲(微秒到毫秒級)的實時資料處理場景,比如實時日誌報表分析。
而且Flink 用流處理去模擬批處理的思想,比Spark 用批處理去模擬流處理的思想擴充套件性更好。