爲什麼說Pravega是實時流處理統一批處理的最後一塊拼圖?

工業物聯網,車聯網和實時欺詐風控的需求正在飛速的發展。越來越多的企業新應用,需要的是快速響應客戶需求,並同時學習和適應不斷變化的行爲模式。同時隨着5G網絡、容器雲、高性能存儲硬件水平的不斷提高,讓實時流處理正在擁有越來越廣泛的市場前景。

流處理在短時間內就能夠對連續生成的數據進行分析產生價值,而無需等待批處理中累積和處理,從攝取到結果的低延遲是流處理技術提供的最爲關鍵的優勢。例如對於車載系統的分析反饋,集羣性能日誌數據的分析告警,金融欺詐風控的精準定位、物聯網煤氣泄漏事件處理等應用而言,高併發下的10ms 級別的低延時意味着最關鍵的商業價值。

流式處理看似簡單 : 只需在數據到達時以快速、持續和無限的方式對其進行處理和操作。但實際情況是,大多數企業並沒有可以支持到PB至EB數據量級,並同時滿足採集速率、故障恢復能力的實時存儲/計算引擎。 隨着適合處理批、實時場景的各種定製化存儲、計算引擎的出現,在業務不斷擴展的過程中,也就無法避免地在企業級別的大數據系統之上堆積複雜性,造成了不小的資源浪費以及運維困難。

流式傳輸迫使系統設計人員重新思考基本的計算和存儲原則。當前的大數據處理系統無論是何種架構都面臨一個共同的問題,即:“計算是原生的流計算,而存儲卻不是原生的流存儲” 。Pravega團隊重新思考了這一基本的數據處理和存儲規則,爲這一場景重新設計了一種新的存儲類型,即原生的流存儲,命名爲”Pravega”,取梵語中“Good Speed”之意。

image

在Pravega之前的流數據處理

在大數據繁榮的早期階段,MapReduce興起,我們可以使用數千臺服務器的集羣分佈式處理大量(TB至PB級別)的數據集。在一個或多個大數據集上運行的這種類型的分佈式計算通常被稱爲批處理作業。批處理作業使各種應用程序能夠從原始數據中獲得價值,這對於擁有龐大用戶數據的企業的成長起到了重要的作用。

對於大型數據集的批處理作業通常具有幾分鐘到幾小時的完成時間,如此長的延遲對於許多應用程序來說並不理想,例如推薦系統,使用最新數據至關重要,但與此同時,處理的精準性也需要保證,即使最小程度的推薦失敗也可能最終導致用戶離開。加之硬件水平的提升,很快我們開始有了更高的要求。我們希望能夠跟上數據產生的步伐得到數據處理的結果,而不是等待數據積累然後才處理。低延遲流處理因此慢慢興起。我們將其稱爲流處理,因爲傳入的數據基本上是事件、消息或樣本的連續流。

許多對實時分析感興趣的公司並不願意放棄MapReduce模型。爲了解決延遲限制,一些應用程序開始使用微批(micro-batch)處理方法:在較短時間內累積的較小塊上運行作業。以Apache Spark Streaming爲代表的微批處理會以秒級增量對流進行緩衝,然後在內存中進行計算。這種方式的實際效果非常好,它確實使應用程序能夠在更短的時間內獲得更高價值。

但由於緩衝機制的存在,微批處理仍然有着較高的延遲,爲了滿足應用的低延遲需求,原生的流處理平臺的研發在近五年中不斷涌現,百花齊放。早期的系統包括S4和Apache Storm。Storm使用成熟,有社區基礎,至今仍然被許多企業廣泛使用。Heron是由Twitter研發的新一代流處理引擎,與Storm兼容的同時性能更優。Apache Samza和Kafka Stream則基於Apache Kafka消息系統來實現高效的流處理。

由於批處理和流處理系統使用着不同的框架,企業爲同時滿足實時和批處理的應用程序,不得不使用兩套獨立的計算基礎架構,計算的結果也同樣進入不同的框架以進行查詢。Storm的創始人Nathan Marz由此提出了Lambda的大數據處理架構(如圖1),將大數據平臺分割成了批處理層、流處理層和應用服務層。Lambda架構遵循讀寫分離,複雜性隔離的原則,整合了離線計算和實時計算,集成Hadoop,Kafka,Storm,Spark,Hbase等各類大數據組件,使得兩種處理能夠在高容錯、低延時和可擴展的條件下平穩運行。

image

圖 1: Lambda 架構

隨着技術和架構的演進,近年來,工程師們開始意識到用流和批兩個詞來區分應用場景,進而給計算框架分類並不合適,兩種處理實質上有着許多共同點。在很多場景下,流和批處理應用同一套處理邏輯,卻不得不因爲框架不同進行重複開發。數據在產生之時就沒有所謂批和流的概念,只是我們的處理方式不同才導致了數據屬性的不同,進而導致了框架的不同。

流和批本來就應該沒有界限!

LinkedIn(Apache Kafka作者,現Confluent CEO)的Jay Kreps提出了Kappa架構,將批處理層、流處理層簡化爲一致性的流處理。谷歌工程師(Apache Beam核心人物)Tyler Akidau提出了Dataflow模型則致力於取代谷歌上一代的MapReduce,將批處理(有限的數據流)視爲流處理(無限的數據流)的特例,重新定義大數據處理的原語。Apache Flink作爲新一代流處理框架的翹楚,其設計遵循Dataflow模型,從根本上統一了批處理和流處理。而Apache Spark也推翻了之前微批處理的設計,推出了Structured Streaming,使用表和SQL的概念進行處理的統一。

有效地提取和提供數據對於流處理應用程序的成功至關重要。由於處理速度和頻率的不同,數據的攝取需要通過兩種策略進行。在典型的Lambda架構中,分佈式文件系統(例如HDFS)負責爲批處理應用提供高併發、高吞吐量的數據,而消息隊列系統(例如RocketMQ)負責爲流處理應用提供數據臨時緩衝,發佈/訂閱功能,數據不進行長時間的持久化保留。兩者無法整合也是目前Kappa架構對歷史數據處理能力有限的原因。

Pravega設計宗旨是成爲流的實時存儲解決方案。應用程序將數據持久化存儲到Pravega中,Pravega的Stream可以有無限制的數量並且持久化存儲任意長時間,使用同樣的Reader API提供尾讀(tail read)和追趕讀(catch-up read)功能,能夠有效滿足兩種處理方式的統一。

Pravega支持僅一次處理 (exactly-once),可在Kappa架構上實現鏈接應用需求,以便將計算拆分爲多個獨立的應用程序,這就是流式系統的微服務架構。我們所設想的架構是由事件驅動、連續和有狀態的數據處理的流式存儲-計算的模式(如圖2)。

image

圖 2: 流處理的簡單生命週期

通過將 Pravega 流存儲與Apache Flink有狀態流處理器相結合,圖2中的所有寫、處理、讀和存儲都是獨立的、彈性的,並可以根據到達數據量進行實時動態擴展。這使我們所有人都能構建以前無法構建的流式應用,並將其從測試原型無縫擴展到生產環境。擁有了Pravega,Kappa架構得以湊齊了最後的拼圖,形成了統一存儲、統一計算的閉環。

流式存儲的要求

我們使用的組件需要爲它而設計,以滿足我們想實現的需求,不然就會像現今的大數據架構那樣,形成複雜性的堆砌。上述內容已經提到,現有的存儲引擎同時無法滿足兩種數據讀取的需求。結合實際的應用場景,總結所需要的特性,企業級流存儲引擎的實現相當有難度,因爲它需要三種看似矛盾的系統功能:

  • 能夠將數據視爲連續和無限的,而不是有限和靜態的
  • 能夠通過自動彈性伸縮數據採集、存儲和處理能力,與負載保持協調一致,持續快速地交付結果
  • 即使在延遲到達或出現亂序數據的情況下,也能連續交付準確的處理結果

讓我們具體深入上述特徵,以當今業界應用最廣的分佈式消息系統Apache Kafka作爲對比,看看Pravega如何以今天存儲無法實現的方式實現它們。

將數據視爲連續和無限的

Kafka源於LinkedIn的日誌採集系統,採用分佈式事務日誌架構進行持久化層的管理。因此,Kafka採用添加到文件的末尾並跟蹤其內容的方式模擬連續和無限的數據流。然而文件既沒有針對此模式進行優化,也受限於本地文件系統的文件描述符以及磁盤容量,因此並非是無限的。對於數據的可靠性,Kafka使用同步副本(in-sync replica)方式進行,佔用了更多的存儲的同時也意味着對吞吐率性能的受損。並且它們利用消息頭部的header記錄元數據以構造數據結構,使得它們不像字節序列那樣通用。

將這些想法拼接在一起, 我們提出了Pravega將從數據的角度支持的連續和無限的特點:

  • Pravega的Stream是一個命名的、持久的、僅追加的、無限的字節序列
  • 使用低延遲追加尾寫並從序列的尾讀(tail read/write)
  • 具有來自序列較舊部分的高吞吐追趕讀(catch-up read)

基於負載的自動(zero-touch)彈性伸縮特性(scale up/scale down)

Kafka通過將數據拆分爲分區,並獨立處理來獲得並行性。這種做法由來已久,Hadoop就使用了分區在HDFS和MapReduce實現了並行化的批處理。對於流式工作負載,傳統的分區有着很大的問題:分區會同時影響讀客戶端和寫客戶端。連續處理的讀寫操作所要求的並行程度通常各不相同,使其鏈接固定數量的分區就會增加實現複雜性。雖然可以添加分區以進行擴展,但這需要手動更新寫客戶端、讀客戶端和存儲。代價高昂,也並非動態縮放。

Pravega,專爲動態和獨立擴展而設計,支持:

  • 許多寫客戶端同時追加寫不相交的數據子集
    • 寫入數據依靠路由鍵(routing key)寫入不同的segment以保證隔離性
    • 讓應用程序爲寫客戶端分配鍵
    • 當鍵空間或寫客戶端發生改變時,對應的存儲不能有約束和改變
  • 許多讀客戶端同時處理不相交的數據子集
    • 讀取的數據分區不依賴於寫入分區
    • 讀取的分區由存儲策略控制
    • 使用segment概念代替物理的分區,且數量根據攝取流量進行自動連續的更新

連續處理數據生成準確的結果

連續計算要得到準確的結果需要僅一次處理(exactly-once)。而僅一次處理語義對數據存儲有着明確的要求,數據寫入必須是:

  • 持久化的
  • 有序的
  • 一致的
  • 事務性的

這些關鍵屬性也是存儲系統設計中最困難的部分。如果沒有事先的設計考慮,後期就只能通過系統重構來完成這些特性。

持久性意味着一旦寫入得到確認,即使遇到組件故障數據也不會丟失。持久性由於與失敗後數據重放相關因而至關重要。沒有持久化的系統意味着數據需要開發人員進行手動歸檔,將永久副本存儲在歸檔系統(通常是HDFS)中。Pravega流式存儲通過數據寫入可持久化的分層存儲保證持久性,用戶能夠永久可靠地保存流數據。

有序性意味着讀客戶端將按照寫入的順序處理數據,Kafka保證了消費者組內部是有序的。對於Pravega這樣的通過路由鍵 (routing key) 來實現分區的系統而言,有序僅對具有相同鍵的數據有意義。例如擁有數百萬傳感器的物聯網系統中,sensor-ID.metric可能作爲鍵,Pravega的Stream能夠保證讀取該傳感器的數據將按其寫入的順序進行。對於使用增量更新計算的聚合函數之類的應用,有序性是必不可少的。

一致性意味着即使面對組件故障,而且無論是從流的尾讀還是追趕讀,所有讀客戶端都會看到給定鍵的相同的有序數據視圖。與持久性一樣,Pravega的一致性僅依靠存儲系統的一致性是不夠的。對Pravega而言,寫客戶端的寫入操作是冪等的,而寫入的數據對於Pravega而言也是不透明的(無法再次進行修改),我們以此實現了強一致性。我們基於Pravega的強一致性還抽象出了狀態同步器的API,用戶可以在此之上構建輕量級的其它分佈式系統的狀態同步。

事務性寫入對於跨鏈接的應用程序一次完全正確是必要的。不僅Pravega本身支持事務性的寫入,更和Apache Flink的Sink集成,在Flink檢查點之間建立事務,通過分佈式兩階段提交協議支持端到端的事務和僅一次處理。

Pravega系列文章計劃

Pravega根據Apache 2.0許可證開源,我們歡迎對流式存儲感興趣的大家加入社區,與Pravega共同成長。下一篇系列文章將會從Pravega本身的架構出發,進一步介紹Pravega的特性細節。之後的文章會逐一介紹Pravega的各大特性、具體實現細節以及使用方法等,敬請大家期待。

本篇文章爲系列文章第一篇,後面系列文章標題如下:

  • Pravega 架構和細節
  • Pravega 應用實例
  • Pravega的動態伸縮特性
  • Pravega的僅一次語義及事務支持
  • 分佈式一致性解決方案:狀態同步器(StateSynchronizer)
  • 與Apache Flink集成使用

參考:

  1. http://pravega.io
  2. http://blog.pravega.io/2017/04/09/storage-reimagined-for-a-streaming-world/
  3. http://blog.pravega.io/2017/12/14/i-have-a-stream/

作者介紹

滕昱: 就職於DellEMC非結構化數據存儲部門(Unstructured Data Storage) 團隊並擔任軟件開發總監。2007年加入DellEMC以後一直專注於分佈式存儲領域。參加並領導了中國研發團隊參與兩代DellEMC對象存儲產品的研發工作並取得商業上成功。從2017年開始,兼任Streaming存儲和實時計算系統的設計開發工作。

周煜敏:復旦大學計算機專業研究生,從本科起就參與DellEMC分佈式對象存儲的實習工作。現參與Flink相關領域研發工作。

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