Kafka Streams與其餘流處理平臺的差別在哪裏?

Kafka Streams與其餘流處理平臺的差別在哪裏?

本文已收錄GitHub,更有互聯網大廠面試真題,面試攻略,高效學習資料等git

近些年來,開源流處理領域涌現出了不少優秀框架。光是在 Apache 基金會孵化的項目,關於流處理的大數據框架就有十幾個之多,好比早期的 Apache Samza、ApacheStorm,以及這兩年火爆的 Spark 以及 Flink 等。github

應該說,每一個框架都有本身獨特的地方,也都有本身的缺陷。面對這衆多的流處理框架,咱們應該如何選擇呢?在本文彙總,我就來梳理幾個主流的流處理平臺,並重點分析一下 KafkaStreams 與其餘流處理平臺的差別。面試

什麼是流處理平臺?

首先,咱們有必要了解一下流處理平臺的概念。「Streaming Systems」一書是這麼定義「流處理平臺」的:流處理平臺(Streaming System)是處理無限數據集(Unbounded Dataset)的數據處理引擎,而流處理是與批處理(Batch Processing)相對應的數據庫

所謂的無限數據,是指數據永遠沒有盡頭。流處理平臺是專門處理這種數據集的系統或框架。固然,這並非說批處理系統不能處理這種無限數據集,只是一般狀況下,它更擅長處理有限數據集(Bounded Dataset)。架構

那流處理和批處理究竟該如何區分呢?下面這張圖應該能幫助你快速且直觀地理解它們的區別。框架

Kafka Streams與其餘流處理平臺的差別在哪裏?

好了,如今我來詳細解釋一下流處理和批處理的區別。分佈式

長期以來,流處理給人的印象一般是低延時,可是結果不許確。每來一條消息,它就能計算一次結果,但因爲它處理的大可能是***數據,可能永遠也不會結束,所以在流處理中,咱們很難精確描述結果什麼時候是精確的。理論上,流處理的計算結果會不斷地逼近精確結果。ide

可是,它的競爭對手批處理則正好相反。批處理能提供準確的計算結果,但每每延時很高。微服務

所以,業界的大神們揚長避短,將二者結合在一塊兒使用。一方面,利用流處理快速地給出不那麼精確的結果;另外一方面,依託於批處理,最終實現數據一致性。這就是所謂的Lambda 架構學習

延時低是個很好的特性,但若是計算結果不許確,流處理是沒法徹底替代批處理的。所謂計算結果準確,在教科書或文獻中有個專屬的名字,叫正確性(Correctness)。能夠這麼說,目前難以實現正確性是流處理取代批處理的最大障礙,而實現正確性的基石是精確一次處理語義(Exactly Once Semantics,EOS)。

這裏的精確一次是流處理平臺能提供的一類一致性保障。常見的一致性保障有三類:

  • 至多一次(At most once)語義:消息或事件對應用狀態的影響最多隻有一次。
  • 至少一次(At least once)語義:消息或事件對應用狀態的影響最少一次。
  • 精確一次(Exactly once)語義:消息或事件對應用狀態的影響有且只有一次。

注意,我這裏說的都是對應用狀態的影響。對於不少有反作用(Side Effect)的操做而言,實現精確一次語義幾乎是不可能的。舉個例子,假設流處理中的某個步驟是發送郵件操做,當郵件發送出去後,假若後面出現問題要回滾整個流處理流程,已發送的郵件是無法追回的,這就是所謂的反作用。當你的流處理邏輯中存在包含反作用的操做算子時,該操做算子的執行是沒法保證精確一次處理的。所以,咱們一般只是保證這類操做對應用狀態的影響精確一次罷了。後面咱們會重點討論 Kafka Streams 是如何實現 EOS 的。

本文討論的流處理既包含真正的實時流處理,也包含微批化(Microbatch)的流處理。所謂的微批化,其實就是重複地執行批處理引擎來實現對無限數據集的處理。典型的微批化實現平臺就是Spark Streaming

Kafka Streams的特點

相比於其餘流處理平臺,Kafka Streams 最大的特點就是它不是一個平臺,至少它不是一個具有完整功能(Full-Fledged)的平臺,好比其餘框架中自帶的調度器和資源管理器,就是 Kafka Streams 不提供的。

Kafka 官網明肯定義 Kafka Streams 是一個Java 客戶端庫(Client Library)。你可使用這個庫來構建高伸縮性、高彈性、高容錯性的分佈式應用以及微服務

使用 Kafka Streams API 構建的應用就是一個普通的 Java 應用程序。你能夠選擇任何熟悉的技術或框架對其進行編譯、打包、部署和上線。

在我看來,這是 Kafka Streams 與 Storm、Spark Streaming 或 Flink 最大的區別。

Java 客戶端庫的定位既能夠說是特點,也能夠說是一個缺陷。目前 Kafka Streams 在國內推廣緩慢的一個重要緣由也在於此。畢竟,不少公司但願它是一個功能完備的平臺,既能提供流處理應用 API,也能提供集羣資源管理與調度方面的能力。因此,這個定位究竟是特點仍是缺陷,仁者見仁、智者見智吧。

Kafka Streams與其餘框架的差別

接下來,我從應用部署、上下游數據源、協調方式和消息語義保障(SemanticGuarantees)4 個方面,詳細分析一下 Kafka Streams 與其餘框架的差別。

應用部署

首先,咱們從流處理應用部署方式上對 Kafka Streams 及其餘框架進行區分。

咱們剛剛提到過,Kafka Streams 應用須要開發人員自行打包和部署,你甚至能夠將Kafka Streams 應用嵌入到其餘 Java 應用中。所以,做爲開發者的你,除了要開發代碼以外,還要自行管理 Kafka Streams 應用的生命週期,要麼將其打包成獨立的 jar 包單獨運行,要麼將流處理邏輯嵌入到微服務中,開放給其餘服務調用。

但不管是哪一種部署方式,你須要本身處理,不要期望 Kafka Streams 幫你作這些事情。

相反地,其餘流處理平臺則提供了完整的部署方案。我以 Apache Flink 爲例來解釋一下。在 Flink 中,流處理應用會被建模成單個的流處理計算邏輯,並封裝進 Flink 的做業中。相似地,Spark 中也有做業的概念,而在 Storm 中則叫拓撲(Topology)。做業的生命週期由框架來管理,特別是在 Flink 中,Flink 框架自行負責管理做業,包括做業的部署和更新等。這些都無需應用開發人員干預。

另外,Flink 這類框架都存在資源管理器(Resource Manager)的角色。一個做業所需的資源徹底由框架層的資源管理器來支持。常見的資源管理器,如 YARN、Kubernetes、Mesos 等,比較新的流處理框架(如 Spark、Flink 等)都是支持的。像 Spark 和 Flink這樣的框架,也支持 Standalone 集羣的方式,即不借助於任何已有的資源管理器,徹底由集羣本身來管理資源。這些都是 Kafka Streams 沒法提供的。

所以,從應用部署方面來看,Kafka Streams 更傾向於將部署交給開發人員來作,而不是依賴於框架本身實現。

上下游數據源

談完了部署方式的差別,咱們來講說鏈接上下游數據源方面的差別。簡單來講,KafkaStreams 目前只支持從 Kafka 讀數據以及向 Kafka 寫數據。在沒有 Kafka Connect 組件的支持下,Kafka Streams 只能讀取 Kafka 集羣上的主題數據,在完成流處理邏輯後也只能將結果寫回到 Kafka 主題上。

反觀 Spark Streaming 和 Flink 這類框架,它們都集成了豐富的上下游數據源鏈接器(Connector),好比常見的鏈接器 MySQL、ElasticSearch、HBase、HDFS、Kafka等。若是使用這些框架,你能夠很方便地集成這些外部框架,無需二次開發。

固然,因爲開發 Connector 一般須要同時掌握流處理框架和外部框架,所以在實際使用過程當中,Connector 的質量良莠不齊,在具體使用的時候,你能夠多查查對應的jira 官網,看看有沒有明顯的「坑」,而後再決定是否使用。

在這個方面,我是有前車可鑑的。曾經,我使用過一個 Connector,我發現它在讀取Kafka 消息向其餘系統寫入的時候彷佛老是重複消費。費了不少周折以後,我才發現這是一個已知的 Bug,並且早就被記錄在 jira 官網上了。所以,我推薦你多逛下 jira,也許能提早避開一些「坑」。

總之,目前 Kafka Streams 只支持與 Kafka 集羣進行交互,它沒有提供開箱即用的外部數據源鏈接器

協調方式

在分佈式協調方面,Kafka Streams 應用依賴於 Kafka 集羣提供的協調功能,來提供高容錯性和高伸縮性

Kafka Streams 應用底層使用了消費者組機制來實現任意的流處理擴縮容。應用的每一個實例或節點,本質上都是相同消費者組下的獨立消費者,彼此互不影響。它們之間的協調工做,由 Kafka 集羣 Broker 上對應的協調者組件來完成。當有實例增長或退出時,協調者自動感知並從新分配負載。

我畫了一張圖來展現每一個 Kafka Streams 實例內部的構造,從這張圖中,咱們能夠看出,每一個實例都由一個消費者實例、特定的流處理邏輯,以及一個生產者實例組成,而這些實例中的消費者實例,共同構成了一個消費者組。

Kafka Streams與其餘流處理平臺的差別在哪裏?

經過這個機制,Kafka Streams 應用同時實現了高伸縮性和高容錯性,而這一切都是自動提供的,不須要你手動實現。

而像 Flink 這樣的框架,它的容錯性和擴展性是經過專屬的主節點(Master Node)全局來協調控制的。

Flink 支持經過 ZooKeeper 實現主節點的高可用性,避免單點失效:某個節點出現故障會自動觸發恢復操做。這種全局性協調模型對於流處理中的做業而言很是實用,但不太適配單獨的流處理應用程序。緣由就在於它不像 Kafka Streams 那樣輕量級,應用程序必需要實現特定的 API 來開啓檢查點機制(checkpointing),同時還須要親身參與到錯誤恢復的過程當中。

應該這樣說,在不一樣的場景下,Kafka Streams 和 Flink 這種重量級的協調模型各有優劣。

消息語義保障

咱們剛剛提到過 EOS,目前不少流處理框架都宣稱它們實現了 EOS,也包括 KafkaStreams 自己。關於精確一次處理語義,有一些地方須要澄清一下。

實際上,當把 Spark、Flink 與 Kafka 結合使用時,若是不使用 Kafka 在 0.11.0.0 版本引入的冪等性 Producer 和事務型 Producer,這些框架是沒法實現端到端的 EOS 的。

由於這些框架與 Kafka 是相互獨立的,彼此之間沒有任何語義保障機制。但若是使用了事務機制,狀況就不一樣了。這些外部系統利用 Kafka 的事務機制,保障了消息從 Kafka 讀取到計算再到寫入 Kafka 的全流程 EOS。這就是所謂的端到端精確一次處理語義。

以前 Spark 和 Flink 宣稱的 EOS 都是在各自的框架內實現的,沒法實現端到端的 EOS。只有使用了 Kafka 的事務機制,它們對應的 Connector 纔有可能支持端到端精確一次處理語義。

Spark 官網上明確指出了用戶若要實現與 Kafka 的 EOS,必須本身確保冪等輸出和位移保存在同一個事務中。若是你不能本身實現這套機制,那麼就要依賴於 Kafka 提供的事務機制來保證

而 Flink 在 Kafka 0.11 以前也宣稱提供 EOS,不過是有前提條件的,即每條消息對Flink應用狀態的影響有且只有一次。

舉個例子,若是你使用 Flink 從 Kafka 讀取消息,而後不加任何處理直接寫入到 MySQL,那麼這個操做就是無狀態的,此時 Flink 沒法保證端到端的 EOS。

換句話說,Flink 最後寫入到 MySQL 的 Kafka 消息可能有重複的。固然,Flink 社區自 1.4版本起正式實現了端到端的 EOS,其基本設計思想正是基於 Kafka 0.11 冪等性 Producer的兩階段提交機制。

兩階段提交(2-Phase Commit,2PC)機制是一種分佈式事務機制,用於實現分佈式系統上跨多個節點事務的原子性提交。下面這張圖來自於神書「Designing Data-IntensiveApplications」中關於 2PC 講解的章節。它清晰地描述了一次成功 2PC 的過程。在這張圖中,兩個數據庫參與到分佈式事務的提交過程當中,它們各自作了一些變動,如今須要使用2PC 來保證兩個數據庫的變動被原子性地提交。如圖所示,2PC 被分爲兩個階段:Prepare 階段和 Commit 階段。只有完整地執行了這兩個階段,這個分佈式事務纔算是提交成功。

Kafka Streams與其餘流處理平臺的差別在哪裏?

分佈式系統中的 2PC 常見於數據庫內部實現或以 XA 事務的方式供各類異質系統使用。Kafka 也借鑑了 2PC 的思想,在 Kafka 內部實現了基於 2PC 的事務機制。

可是,對於 Kafka Streams 而言,狀況就不一樣了。它自然支持端到端的 EOS,由於它原本就是和 Kafka 緊密相連的。

下圖展現了一個典型的 Kafka Streams 應用的執行邏輯。

Kafka Streams與其餘流處理平臺的差別在哪裏?

一般狀況下,一個 Kafka Streams 須要執行 5 個步驟:

  1. 讀取最新處理的消息位移;
  2. 讀取消息數據;
  3. 執行處理邏輯;
  4. 將處理結果寫回到 Kafka;
  5. 保存位置信息。

這五步的執行必須是原子性的,不然沒法實現精確一次處理語義。

在設計上,Kafka Streams 在底層大量使用 Kafka 事務機制和冪等性 Producer 來實現多分區的原子性寫入,又由於它只能讀寫 Kafka,所以 Kafka Streams 很容易地就實現了端到端的 EOS。

總之,雖然 Flink 自 1.4 版本也提供與 Kafka 的 EOS,但從適配性來考量的話,應該說Kafka Streams 與 Kafka 的適配性是最好的。

總結

好了,咱們來小結一下。本文重點分享了 Kafka Streams 與其餘流處理框架或平臺的差別。總的來講,Kafka Streams 是一個輕量級的客戶端庫,而其餘流處理平臺都是功能完備的流處理解決方案。這是 Kafka Streams 的特點所在,但同時可能也是缺陷。不過,我認爲不少狀況下咱們並不須要重量級的流處理解決方案,採用輕量級的庫 API 幫助咱們實現實時計算是很方便的情形,我想,這或許是 Kafka Streams 將來的破局之路吧。

相關文章
相關標籤/搜索