槓上Spark、Flink?Kafka為何轉型流資料平臺

weixin_33763244發表於2018-12-10

AI前線導讀: 訊息中介軟體系統(比如RabbitMQ、Kafka、Pulsar等)是現代實時資料或者流資料基礎架構的關鍵環節。它通常作為一個資料管道,連結了各種業務前臺和資料後臺(比如數倉等)。但是隨著越來越多的企業應用開始採納流計算作為資料的計算引擎,以及基礎架構的容器化、雲化和無伺服器化(Serverless),這些訊息系統也隨之發生變化,逐步向流資料平臺演進。在這篇文章中,筆者根據自己在這個領域從業多年的經驗,詳細解讀訊息系統的演化歷史,不同訊息系統在基礎設施變革的浪潮中面臨的挑戰,以及他們相應的優勢和劣勢,並對訊息系統怎麼跟已有的計算框架進行整合,以及對未來可能的發展方向進行探討。

本文是InfoQ特別策劃《Kafka的七年之癢》專題系列文章的第二篇,第一篇文章回顧見《Kafka從0.7到1.0:過去7年我們踩過哪些坑?》

更多幹貨內容請關注微信公眾號“AI前線”(ID:ai-front)

1. 訊息系統的演化歷史

\"image\"

訊息系統作為一個核心的基礎架構元件由來已久,而且運用廣泛。整個訊息系統的演化程式,大致可以分為三個階段:

  • 1.0時代:JMS以及各種MQ

  • 2.0時代:Kafka的實時管道時代

  • 3.0時代:流資料平臺時代 (Kafka和Pulsar)

1.0 - MQ時代

訊息系統作為一個基礎機構的元件,通常用於連線不同的軟體服務。這些服務可以相互連線,形成一個更大的服務。或者,它也用於將使用者裝置和後臺服務進行連線。訊息系統通過將訊息的分發和接收分離來實現應用服務的非同步和解耦。

或許你正在考慮進行資料投遞、非阻塞操作,或者推送通知;或者你想要實現釋出/訂閱,非同步處理,或者工作佇列。所有這些都屬於訊息系統的模式。這些訊息系統通過JMS或者AMQP的訊息規範或者協議進行通訊。比如RabbitMQ就是AMQP的一個訊息系統實現。它可以為你的應用服務提供一個通用的訊息傳送和接收平臺,並且保證訊息在傳輸過程中的安全。

舉個例子,對於一個大型的系統來說,它通常會由很多不同的元件或者子系統構成。如果這些子系統直接使用傳統的IPC或者Socket網路通訊構建,那麼模組和子系統之間的耦合性會很大,並不適合進行擴充套件;而且它同時需要考慮各種問題——比如資料的傳送方和接收方怎麼進行容錯處理,如何做負載均衡,如何處理系統擴充套件等。而一個訊息系統就可以解決上述所有問題。

在這個時代,訊息系統主要以圍繞JMS、AMQP等標準化的訊息規範和訊息協議設計的系統實現為代表,比如ActiveMQ,RabbitMQ等。訊息系統在這個時代主要用於線上業務,用來解耦系統的複雜度。

2.0 - 實時管道時代

訊息系統演化的2.0時代,其實是一個實時管道的時代。而Kafka是這個時代的典型代表系統。Kafka是2010年左右在Linkedin研發的一套分散式訊息系統。當時的Linkedin和很多網際網路公司一樣,分很多的組,有很多的資料產品,每天需要採集非常多的資料。這些資料都是由不同資料來源實時生成,比如使用者活躍度、日誌等。如果資料的生產者和消費者之間採用點對點的方式進行資料傳輸,那麼運維的人力和物力成本就會很高。於是Linkedin需要一個集中式的資料管道,所有的業務方都只要跟這個資料管道打交道就可以,不再需要進行點對點的資料傳輸。

從2010年開始,Linkined嘗試了不同的訊息系統。但是發現1.0時代的訊息系統都有兩個比較通用的缺陷:一是當消費者出現,無法及時消費資料的時候,訊息資料可能會被丟棄;二是可擴充套件性上,並不能很好的配合網際網路的資料規模。Kafka就誕生在這樣的背景下。

Kafka的設計理念很簡單,就是一個以append-only日誌作為核心的資料儲存結構。簡單來說,就是Kafka把資料以日誌的方式進行組織,所有的資料以追加日誌的方式寫到日誌的最末端,對日誌的讀取按照順序進行讀取。這樣儘可能講資料的讀寫按照順序進行操作,這樣可以做到比傳統MQ更高的吞吐。此外,資料以Topic為單位作為粒度,按照分割槽進行切分,儲存在不同的伺服器上。資料的釋出和訂閱都基於Topic,資料更新時,消費端的客戶端會把它們從伺服器上拉去下來。

Kafka變得流行,並且成為那個時代的資料管道,得益於Storm的流行。Storm的興起和Lambda架構的引入彌補了Hadoop大資料生態在速度和時延上的短板。大量的網際網路公司比如Twitter等,開始使用Storm和Lambda架構,Kafka的實時管道特性,配合Storm的流計算,使之開始變得流行。

3.0 - 流資料平臺時代

訊息系統演化的第三個階段是流資料平臺。這包含兩方面的含義,其一是流資料,其二是平臺化。流資料,廣義上來講,是相對於批處理時代的靜態資料而言的。這其中包括微服務、事件驅動架構(Event-Driven-Architecture)的流行,物聯網的興起等。而平臺化意味著訊息系統需要能夠作為一個平臺系統去支撐不同的業務服務、不同的租戶管理,而不再是一個簡單的資料管道。Apache Pulsar就是新一代訊息系統的代表。

這些系統的誕生,主要與以下幾個因素有關:

首先,傳統的訊息系統比如各種MQ和Kafka並不能很好地支援平臺化,或者隨著資料規模的增長,業務負載多樣性的增加,這些系統開始暴露大量問題:基本上傳統的訊息系統都是以分割槽為主的架構設計,緊耦合了訊息服務(計算)和訊息儲存,而且儲存模型都過於簡單或者太依賴於檔案系統。隨著Topics資料量的增加,或者資料重要性(不丟資料)的加強,這些系統的效能會急劇下降。

其次,基礎架構的容器化。從2012年開始,Mesos的流行、Docker的興起,到現在Kubernetes一統天下,整個基礎架構正在全面往容器化發展。任何緊耦合計算和儲存的架構並不能很好地使用新的容器化架構。訊息系統需要一個計算和儲存相互分離的架構設計去更好地適應容器化的變革。

第三,基礎架構的雲化。雲化是一種新的思維方式。首先,不論是公有云還是私有云,架構設計都需要考慮平臺化,也就是多租戶、IO隔離、流控、配額以及安全開始變成訊息系統的標配;其次,架構設計需要考慮如何去使用雲資源(比如雲端儲存等)。

第四,計算框架的批流一體化。無論是Flink還是Spark,流計算還是批計算的邊界已經變得模糊。使用者真正關心的是如何更好更快地使用資料,如何從資料中更快地挖掘出其中的價值。而這其中最核心的思維轉變是,流資料和靜態資料不再是不同的資料,它們其實是同一份資料的兩種不同表徵方式。

第五,計算輕量化,Serverless和事件驅動架構帶來的變革。

2. Kafka的挑戰

正如上文所述,Kafka基本上是當下實時管道的第一選擇。在Kafka 0.8之後,Kafka也在往平臺化的方向發展。現在的Kafka除了最核心的訊息釋出和訂閱之外,還包括了以下一些新興元件,比如:

  • Kafka Connect:用來從Kafka匯入和匯出資料

  • Kafka Streams:輕量化的流計算庫,用於編寫一些簡單的計算任務處理Kafka的資料。

  • 此外,還包含Schema Registry、KSQL等元件。

但是,Kafka在平臺化的過程中,最核心的挑戰在於其架構如何適應雲原生的挑戰。

首先,Kafka以分割槽為中心的架構設計是面向物理機時代的架構設計。它緊耦合了訊息服務(計算)和訊息儲存,Kafka的分割槽跟一臺或者一組物理機強繫結。強繫結帶來的問題是,當處理機器失效或者擴容的過程中,Kafka需要進行昂貴且緩慢的分割槽資料重新均衡的過程。這個過程十分漫長,而且容易出錯。一旦出錯,可能帶來服務的不可用性。

其次,Kafka以分割槽為粒度的儲存設計,導致其並不能很好地利用已有的雲端儲存資源。

最後,Kafka的儲存設計過於簡單,導致其進行多租戶管理、IO隔離以及平臺化轉型過程中,需要解決架構上的很多缺陷。

3. Pulsar的雲原生之路

而近一年多崛起並漸漸被更多開發者瞭解的Apache Pulsar,與Apache Kafka的不同也正好體現在雲原生架構設計上。Apache Kafka在設計上的一些並不能很好地適應於雲原生環境的缺陷,比如訊息服務和訊息儲存的緊耦合、IO並不隔離、基於物理分割槽的儲存模型等,Apache Pulsar在設計之初就很好地避開了——比如計算和儲存分離、分層分片、IO隔離、多租戶管理等。

Apache Pulsar是2012年在Yahoo內部啟動的專案。其最初的設計,就是奔著做Yahoo內部的訊息雲去做的。所以Pulsar從寫第一行程式碼開始,就把租戶的概念做進去了,並吸取了以前系統的經驗和教訓,避免了以前的系統設計上的缺陷。Pulsar在生產線上成功執行了4年後,在2016年九月由Yahoo開源,並在2017年六月捐獻給Apache軟體基金會。Pulsar在今年九月成功畢業成為頂級專案。從開始孵化到最終畢業,總共經歷了9個releases,目前社群總共有23位committers,30多家公司將Pulsar執行在生產線上。

Apache Pulsar作為新興的訊息流資料平臺,除了擁有豐富的特性(比如多租戶管理,IO隔離,多機房複製等)之外,它跟傳統的訊息系統最大的不同是,Pulsar是一個面向容器化設計的雲原生的流資料系統。怎麼來理解這個問題呢?

首先,整個IT的基礎設施是從傳統的物理機模型往容器化模型遷移。容器化對於架構設計的直接影響,就是將原來一體化(Monolithic)的架構按照處理邏輯拆分成小的邏輯單元,並進行容器化。對於分散式系統的設計的影響,通常體現在計算和儲存的分離。儲存和計算的分離通常應用在一些新型的資料庫系統,比如TiDB。Pulsar正是在這種容器化程式中誕生的。Pulsar將系統分為兩層,一層是無狀態的訊息服務(計算)層——Brokers,另外一層是持久化的訊息儲存層——Bookies (via Apache BookKeeper)。計算和儲存分離之後,兩層可以相互獨立擴充套件,如果需要儲存更多的資料,只需要新增儲存節點;如果需要支援更多的生產者和消費者,只需要新增Brokers。此外,因為Brokers變成了一個無狀態的服務元件,容錯處理變得更加容易,從而能夠極速擴容。

其次,基礎架構的雲化,使得使用者更加容易在雲上得到彈性的計算資源和儲存資源。以儲存資源為例,AWS有S3,Azure有Blob Store,而GCP有GCS。傳統的面向物理分割槽模型設計的系統,並不能很好地利用雲端儲存資源。而Pulsar在儲存上做了一個降維的處理。Pulsar把物理分割槽變成了邏輯分割槽,而將儲存粒度從粗粒度的分割槽變成了細粒度的分片(Segment)。因此Pulsar可以將訊息以分片的粒度儲存在不同的雲端儲存中,而向外部使用者依然提供統一的訊息模型。這種分片的架構,更加原生地利用雲端儲存資源。

再次,計算框架的批流一體化,意味著訊息和儲存之間是共性的。訊息的資料是流入系統的最新資料,而這些資料落到儲存上就變成了”歷史“資料,並用於批量計算。而Pulsar將資料的訊息和儲存共性體現在分層和分片的處理上,訊息服務層(Brokers)用來提供訊息的Pub-Sub,用於流式計算;而訊息落地到儲存層,按照分片儲存,則可以進行批式計算。而這種訊息和儲存的共性,讓使用者不在需要區分這個資料是訊息資料還是歷史資料,從而做到真正意義上的批流一體化。

最後,基礎架構的演變從物理機,到虛擬機器,再到容器,以及到現在的Serverless。計算資源的粒度變得越來越細,使用者在使用計算資源的過程中,變得越來越關注於計算的本身。這也是所謂計算輕量化的發展之道。Pulsar在2.0之後,將Serverless的概念引入了流資料平臺,變成了所謂的Pulsar Functions。Functions的誕生就是為了讓使用者更加專注於編寫事件處理邏輯。

4. 輕量化計算和Spark、Flink

在大資料計算的領域,Spark和Flink都是通用的能夠支援超大規模資料處理、支援各種處理型別的計算引擎。Spark從2014年左右開始流行,除了在某些場景比Hadoop MapReduce帶來幾十到上百倍的效能提升之外,還提出了用一個統一的引擎支援批處理、流處理、互動性查詢、機器學習等常見的資料處理場景。而Flink則是在2016年左右開始進入大眾的視野,並憑藉其更優的流處理引擎,批流一體計算等逐漸廣為人知,同時也支援各種處理場景,成為Spark的有利挑戰者。

但是,隨著微服務的興起,以及事件驅動架構的流行,大家慢慢發現,為了編寫一些簡單計算而去部署一套Flink或者Spark,代價有點大,有種殺雞用牛刀的感覺。於是,大家開始琢磨怎麼能夠更加簡化這些計算,並開始在訊息系統上新增輕量化計算。Kafka引入了KStreams,使用了傳統的流計算的概念,只是將計算變得輕量化,不再依賴於某個計算平臺,使用者可以選擇自己最適合的部署方式;而Pulsar則走了截然不同的一條路徑,它跳脫出了傳統流計算的模型,而借鑑了Serverless的概念,將Serverless Function引入了訊息系統內部。使用者可以通過編寫原生的Function來進行任意邏輯的計算。以Function為主導的輕量化計算讓使用者更加關注於計算邏輯本身,適用於一些簡單計算,比如Filtering、Aggregation、Routing等。

資料處理的意義就是挖掘蘊含在資料內部的價值,而且Spark和Flink是通用計算引擎的兩個巨頭,基於訊息系統衍生出來的輕量化計算並不是一種通用計算,不能與已有的通用計算引擎抗衡。但輕量化計算是對於通用計算的一種補充,讓一些微服務的構建以及事件驅動架構的設計變得更加容易。這些訊息流平臺在通用計算方面,還是需要跟Spark和Flink更加緊密地結合。

5. 未來展望

訊息系統作為大資料基礎架構的一個環節,起著至關重要的作用它們也隨著基礎設施的演化而不斷進步。如何更好地使用雲化和容器化的基礎設施,將是每個訊息系統面臨的挑戰。批流一體化和統一的資料表徵,也是下一臺資料平臺需要支援的特性。

作為資料平臺,如何更好地跟已有的計算框架比如Flink和Spark結合,進行批流一體的計算?如何權衡輕量化計算和複雜計算的邊界?不論是Kafka還是Pulsar,都還任重而道遠。

相關文章