槓上Spark、Flink?Kafka爲何轉型流數據平臺

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,都還任重而道遠。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章