當前,流數據平臺的普及率正在飆升。爲了解決日益增加的實時數據處理需求,一些公司正在將其部分大數據基礎架構轉換爲流式處理模型。 基於流數據的基礎架構不只可以更好地解決延遲敏感的數據處理業務需求,同時提供更多深刻業務洞察 ; 另外,流式數據處理平臺讓傳統的數據倉庫建設更加簡單靈活。html
流式基礎架構的關鍵部分是流計算引擎。優秀的流式計算引擎可讓業務即便在有狀態計算的狀況下,也能提供低延遲、高吞吐、強一致性。正則表達式
在本文中,咱們將深刻探討 Flink 的檢查點機制如何工做,以及它如何取代舊架構以實現流容錯和恢復。 咱們測量 Flink 在各類類型的流媒體應用程序中的性能,並經過在 Apache Storm(一種普遍使用的低延遲流處理器)上運行相同系列的實驗來進行效果對比。算法
在流式計算領域,同一套系統須要同時兼具容錯和高性能其實很是難。 在傳統的批處理中,看成業失敗時,能夠簡單地從新運行做業的失敗部分以修復因爲以前失敗致使的數據丟失。 這對於批處理是徹底可行的,由於批處理的數據是靜態的,能夠從頭至尾重放。 在連續的流式處理模型中,這種處理思路是徹底不可行的。數據庫
原則上,數據流是無窮無盡的,不具備開始點和結束點。 一個帶有 Buffer 緩存的數據流或許能夠進行一小段的數據重放、從新計算 (即: 若是系統出錯,系統能夠嘗試從在 Buffer 中緩存的數據流進行從新計算),但出錯時但願從數據流最開始點進行從新計算是不切實際的(例如,一個流做業能夠運行數月之久,當出現系統故障時候致使數據計算出錯不可能參考批處理系統,從幾個月前的數據開始計算)。 此外,與僅具備輸入和輸出的批處理做業相比,流式計算是有狀態的。 這意味着除了輸出以外,系統還須要備份和恢復部分計算 (咱們稱之爲 Operator,下同) 狀態。apache
因爲這些問題帶來的諸多複雜性,開源生態系統多個系統都在嘗試多種方式來解決容錯問題。容錯機制的設計將對框架設計預計編程模型都有深遠的影響,致使難以在現有的流式框架上相似插件機制同樣擴展實現不同的容錯策略。所以,當咱們選擇流式計算內框架時,容錯策略很是重要。編程
接下來,咱們將討論了容錯流式架構的幾種方法,從記錄確認 (record-acknowledgements) 到微批處理 (micro-batching),事務更新(transactional updates)和分佈式快照(distributed snapshots)。 咱們將從如下幾個維度討論各個系統的優缺點,同時最終選出一個適合流式處理的最優 Feature 組合。 咱們將討論:緩存
徹底一次保證:故障後應正確恢復有狀態運算符中的狀態安全
低延遲:越低越好。 許多應用程序須要亞秒級延遲微信
高吞吐量:隨着數據速率的增加,經過管道推送大量數據相當重要網絡
強大的計算模型:框架應該提供一種編程模型,該模型不限制用戶並容許各類各樣的應用程序在沒有故障的狀況下,容錯機制的開銷很低
流量控制:來自慢速操做員的背壓應該由系統和數據源天然吸取,以免因消費者緩慢而致使崩潰或下降性能
咱們遺漏了一個共同特徵,即失敗後的快速恢復,不是由於它不重要,而是由於(1)全部討論的系統都是基於徹底並行的分佈式處理系統,恢復是基礎能力;以及(2)在有狀態的應用程序中,狀態恢復的瓶頸一般在於存儲而非計算框架。
雖然流處理已經在諸如金融等行業中普遍使用多年,但直到最近流式處理才能爲大數據的基礎設施的一部分。 這些都得益於開源的流式大數據處理引擎成熟和發展。 Apache Storm 是開源生態中第一個普遍使用的大規模流處理框架。 Storm 使用上游備份機制和記錄確認機制來保證在失敗後從新處理消息。 請注意,Storm 不保證狀態一致性,任何可變狀態處理都委託給用戶來處理(Storm 的 Trident API 確保狀態一致性,將在下一節中介紹)。
譯者注: 如下內容理解須要讀者必定的 Apache Storm 基礎,請參看 Apache Storm 官方文檔有關 Storm 關鍵概念的描述。
記錄確認的容錯方式以下:當前 Operator 處理完成每條記錄時都會向前一個 Operator 發回針對這條記錄處理過的確認。
Topology 的 Source(譯者注: Storm 的 Source 節點指 Storm 一個做業中負責從流式源頭讀取數據的 Operator) 會保留其產生的全部記錄備份用來處理 Fail 狀況。 當源頭一條記錄的全部派生記錄都被整個 Topology 處理完成,Source 節點就能夠刪除其備份;當系統出現部分 Fail 狀況,例如一條記錄並無收到其下游的派生記錄的確認,Source 就會從新發送該記錄到下游的 Topology 以便從新進行計算。 這種處理機制能夠保證整個處理過程不會丟失數據,但頗有可能致使同一條記錄被屢次發送到下游進行處理(咱們稱之爲「at least once」)。 Storm 使用一種巧妙的機制來實現這種容錯方式,每一個源記錄只須要幾個字節的存儲來跟蹤確認。 Twitter Heron 保持與 Storm 相同的確認機制,但提升了記錄重放的效率(從而提升了恢復時間和總體吞吐量)。
單獨的記錄確認容錯體系結構,不管其性能如何,都沒法提供 exactly-once(精確一次) 的保證,Storm 將規避重複數據的問題交給了流式處理應用開發者去處理。 固然,對於某些應用程序而言,數據小部分重複能夠接受的,但仍然有更多的場景沒法接受數據不許確的狀況。另外,Storm 的容錯機制還帶來了吞吐不夠以及流控問題, 特別是在 backpressure(反壓) 狀況下,記錄確認的容錯方式會致使上游節點錯誤地認爲數據處理出現了 Fail(實際上僅僅是因爲 backpressure 致使記錄處理不及時,而沒法 ack)。上述 Storm 的種種問題最終演化出基於微批處理的流式架構。
上節討論到,Storm 和以及更早前的流式傳輸系統沒法提供對大規模應用程序相當重要的一些 Feature,特別是高吞吐量,快速並行恢復,以及託管狀態的一次性語義。 這致使了下一階段的流式系統演化。
以後,具有容錯能力的下一個發展階段到了微批處理,或者說流離散化 (stream discretization,即將連續的流切分爲一個個離散的、小批次的微批進行處理)。這個出發點很是簡單:流式處理系統中的算子都是在 record 級別進行計算同步和容錯,由此帶來了在 record 如此低層次上進行處理的複雜和開銷。很簡單嘛,咱們就把連續的數據流不要切分到 record 級別,而是收斂切分爲一批一批微批的、原子的數據進行相似 Batch 的計算。這樣,每一個 batch 的數據可能會成功或者失敗處理,咱們就對當前失敗的這一小批數據進行處理便可。
微批處理本質上一種批處理模型,顯然能夠利用現有的批處理引擎就能夠完成流式計算。例如,能夠在批處理引擎(Spark)提供流功能(這是 Spark Streaming 背後的基本機制),當前它也能夠應用於流引擎之上(例如, Storm)提供一次性保證和狀態恢復(這是 Storm Trident 背後的想法)。 在 Spark Streaming 中,每次的微批量計算都是一個 Spark 做業,而在 Trident 中,每一個微批次都是一個大型記錄,微批次中的全部記錄都會合並進入一個大型記錄。
基於微批處理的系統能夠實現上面列出的至關多的需求(確切一次保證,高吞吐量),但它們還有不少不足之處:
編程模型:爲了實現其目標,例如,Spark Streaming 將編程模型從流式更改成微批處理。 這意味着用戶不能再在檢查點間隔的倍數以外的時段中窗口數據,而且模型不能支持許多應用程序所需的基於計數或會話窗口。 這些都是應用程序開發人員須要的需求。具備能夠改變狀態的連續運算符的純流模型爲用戶提供了更大的靈活性。
流量控制:使用基於時間的數據切分爲微批的處理方式仍然具備 backpressure 固有問題。 若是某個下游的 Operator 處理較慢(例如,計算密集型 Operator 處理性能跟不上或者向外部存儲寫出數據較慢),此時若是負責數據流切分的 Operator 速度快於下游的阻塞節點,就會致使數據切分比原有的配置時間更長。 這致使愈來愈多的批次在內存排隊等待被處理,最終內存 OOM,或者微批的時間間隔增大致使數據不精確。
延遲:微批處理顯然加大了流計算延遲,一個微批做業的延遲最好狀況也只能到微批的間隔時間。 一般狀況下,亞秒級別的延遲對於一些簡單應用程序足夠,但一個較爲複雜的流式處理任務,例如單個做業內部存在多個階段,每一個階段存在大量分佈式數據 shuffle 狀況,很容易將整個做業延遲拉長的數秒甚至數十秒。
微批處理模型的最大限制多是它鏈接了兩個不該鏈接的概念:應用程序定義的窗口大小和系統內部恢復間隔。 假設一個程序(下面是示例 Flink 代碼)每 5 秒聚合一次記錄:
這些應用很是適合微批量模型。 系統累積 5 秒的數據,對它們求和,並在對流進行一些轉換後聚合計算。 下游數據應用程序能夠直接使用上述 5 秒聚合的結果進行數據消費,例如在儀表板上顯示。 可是,如今假設 backpressure 效應開始起做用(例如,因爲計算密集型的 transformRecords 函數),或者 devops 團隊決定經過將間隔增長到 10 秒來控制做業的吞吐量。 而後,在出現 backpressure 狀況下,微批量大小不受控制地動態進行改變,或者直接變爲 10 秒。 這意味着下游應用程序(例如,包含最近 5 秒統計的 Web 儀表板)讀取的聚合數據是錯誤的,下游應用程序須要本身處理此問題。 這樣,流計算系統因爲性能或者吞吐問題,直接致使了運行數據錯誤。
微批處理能夠實現高吞吐量和一次性保證,但這些功能室以喪失低延遲,流量控制和純流式編程模型爲代價滴。 顯然,咱們須要思考清楚的是,是否有可能實現一箭雙鵰:在保持持續計算 (continuous process) 的運算符模型的全部優點,同時兼備一致性、高吞吐量等優點。 後面討論的後續流式架構實現了這種 Feature 的組合,並將微批處理做爲流式處理的基本模型。
注意:一般微批處理被認爲是一次處理一條記錄的替代方法。 這是見文生義的作法:所謂的連續計算並非連續地一次處理一條記錄。 實際上,全部精心設計的流計算系統(包括下面討論的 Flink 和 Google Dataflow)在經過網絡傳輸以前會緩衝許多記錄,同時又具有流式連續處理能力。
如何作到魚和熊掌兼得?在保持連續計算模型(低延遲,反壓流控,狀態管理等)的好處,同時保證作到數據處理的準確一致。一種強大而不失優雅的方式是原子地記錄數據的處理以及狀態的更新 (譯者注: 相似數據的 WAL 日誌)。 一旦系統出現 Fail,可從記錄的日誌中恢復咱們須要的中間計算狀態和須要處理數據。
在 Google Cloud Dataflow 中實現相似的模型。 系統將計算模型抽象爲一次部署並長期運行持續計算的 Operator DAG。 在 Dataflow 中,數據的 shuffle 是流式的而非批模式,同時計算結果亦不須要物化 (數據的計算結果放在內存中)。 這種模型不只解決了流式計算低延遲問題,同時還自然支持天然流量控制機制,由於 DAG 不一樣階段的 Operator 之間存有中間結果的 Buffer,這些中間緩衝區能夠緩解反壓,直到反壓惡化到最源頭的 Operator,即 DataFlow Source 節點。而基於 Pull 模型的流式數據源,如 Kafka 消費者能夠處理這個問題,即 Source 節點的中間結果 Buffer 會出現積壓致使讀取 Kafka 變慢,但不會影響上游的流數據採集。 系統還支持一套乾淨的流編程模型,支持複雜的窗口,同時還提供對狀態的更新操做。 值得一提的是,這套流編程模型包含微批量模型。
例如,下面 Google Cloud Dataflow 程序(請參閱:https://cloud.google.com/dataflow/model/windowing )會建立一個會話窗口,若是針對某個 Key 在 10 分鐘內都沒有數據達到,則會觸發該會話窗口 (譯者注: 例如某個用戶在訪問 APP 期間中斷了 10 分鐘沒有操做)。 而間隔 10 分鐘後,若是新的數據到達,系統將建立一個新的會話窗口。
這種數據的處理方式在流式模型中很容易實現,但在微批量模型中很難實現,由於數據窗口的定義不對應於固定的微批量大小。
這種架構中的容錯設計以下:經過 Operator 的每一箇中間記錄,和本 Operator 計算帶來的狀態更新,以及有本條記錄派生的新記錄,一塊兒作一次原子事務並提交到事務性日誌系統或者數據庫系統。 在系統出現失敗的狀況下,以前數據庫的記錄將被重放,用於恢復計算的中間狀態,同時將丟失沒有來得及計算的數據從新讀取進行計算。
Apache Samza 遵循相似的方法,但只能提供 at-least-once 保證 ,由於它使用 Apache Kafka 做爲後臺存儲。 Kafka(如今)不提供事務,所以對狀態和派生流記錄的更新不能做爲原子事務一塊兒提交。
事務更新體系結構具備許多優勢。 事實上,它實現了咱們在本文開頭提出的全部需求。 該體系結構的基礎是可以頻繁地寫入具備高吞吐量的分佈式容錯存儲。 分佈式快照(在下一節中進行了解釋)將拓撲的狀態做爲一個總體進行快照,從而減小了對分佈式存儲的寫入量和頻率。
提供 exactly-once 流式處理語義保證的核心問題就是 肯定當前流式計算的狀態 (包括正在處理的數據,以及 Operator 狀態),生成該狀態的一致快照,並存儲在持久存儲中。若是能夠常常執行狀態保存的操做,則從故障恢復意味着僅從持久存儲中恢復最新快照,將源頭 Source 回退到快照生成時刻再次進行」播放」。Flink 的狀態算法在這篇論文有詳細說明,如下咱們給出一個簡單總結。
Flink 的快照機制基於 Chandy 和 Lamport 於 1985 年設計的算法,用於生成分佈式系統當前狀態的一致快照(請參閱此處的詳細介紹 ),不會丟失信息且不記錄重複項。 Flink 使用的是 Chandy Lamport 算法的一個變種,按期對正在運行的流拓撲的狀態作快照,並將這些快照存儲到持久存儲(例如,存儲到 HDFS 或內存中文件系統)。 這些作快照的頻率是可配置的。
這相似於微批處理方法,其中兩個檢查點之間的全部計算都做爲一個總體原子地成功或失敗。 然而,這個就是二者惟一的相似點。 Chandy Lamport 算法的一個重要特色是咱們永遠沒必要按流處理中的「暫停」按鈕,用來等待檢查點完成後安排下一次 Batch 數據處理。 相反,常規數據處理始終保持運行,而狀態持久化僅在後臺發生。 如下引用原始論文,
全局狀態檢測算法應該被設計在基礎 (業務) 計算之上:它必須與此基礎 (業務) 計算同時並行進行,但不能侵入改變基礎 (業務) 計算。
所以,該架構結合了遵循真正的持續計算模型(低延遲,流量控制和真正的流編程模型)和高吞吐量的優勢,而且也是 Chandy-Lamport 算法可證實的一次性保證。 除了持久化有狀態計算的狀態(每一個其餘容錯機制也須要這樣作)以外,這種容錯機制幾乎沒有開銷。 對於小狀態(例如,計數或其餘統計摘要),這種持久化開銷一般可忽略不計,而對於大狀態,狀態持久化間隔須要流計算應用開發者在吞吐量和恢復時間之間進行權衡。
最重要的是,該架構將應用程序開發與流量控制、吞吐量控制分開。 更改快照持久化的間隔時間對流做業的結果徹底沒有影響,所以下游應用程序能夠安全地依賴於接收正確的結果。
Flink 的檢查點機制基於 stream barriers(能夠理解爲Chandy Lamport 中的「標記」),這些 barrier 像正常的業務數據同樣在 Operator 和 Operator 之間的數據管道中流動。 Flink 的檢查點的描述來自於 Flink 社區文檔 ) 。
Barrier 在 Source 節點中被注入到普通流數據中(例如,若是使用 Apache Kafka 做爲源,Barrier 將與 Kafka 的讀取偏移對齊),而且做爲數據流的一部分與數據記錄一塊兒流過下游的 DAG。 Barrier 將業務數據流分爲兩組:當前快照的一部分(Barrier 表示檢查點的開始),以及屬於下一個快照的那些組。
Barrier 流向下游並在經過 Operator 時觸發狀態快照。 Operator 首先將 Barrier 與全部傳入的流分區(一般 Barrier 具備多個輸入)對齊,上游來源較快的流分區將被緩衝數據以等待來源較慢的流分區。 當 Operator 從每一個輸入流分區都收到 Barrier 時,它會檢查其狀態(若是有)並寫入持久存儲,這個過程咱們稱之爲狀態寫檢查。一旦完成狀態檢查點,Operator 就將 Barrier 向下遊轉發。 請注意,在此機制中,若是 Operator 支持,則狀態檢查點既能夠是異步(在寫入狀態時繼續處理),也能夠是增量(僅寫入更改)。
一旦全部數據寫出端 (即 Flink Sink 節點) 都收到 Barrier,當前檢查點就完成了。 故障恢復意味着只需恢復最新的檢查點狀態,並從最新的 Barrier 記錄的偏移量從新啓動 Source 節點。 分佈式快照在咱們在本文開頭所要達到的全部需求中得分很高。 它們實現了高吞吐量、一次性保證,同時保留了連續的 Operator 模型、低延遲以及天然流量控制。
咱們從這篇文章開始,列出了來自分佈式流體系結構的需求。下表總結了咱們討論的每一個體繫結構如何支持這些功能。
爲了進一步說明 Apache Flink™的性能,咱們設計了一系列實驗,用以研究 Flink 的吞吐,延遲以及容錯機制的影響。下面全部實驗均在 Google Compute Engine 上進行,使用 30 個實例,每一個實例包含 4 核和 15GB 內存。全部 Flink 測試均使用截至 7 月 24 日的最新代碼修訂版進行,全部 Storm 測試均使用 0.9.3 版。若有須要,你們能夠在此處找到用於評估的全部代碼。
同時,爲了更好進行橫向比較,咱們也提供了在 Apache Storm 上面運行相同程序的結果。如前面文章所介紹,Apache Storm 曾經是最普遍使用的流式處理系統之一,它核心機制是實現了"記錄確認 (譯註: record acknowledgements)"以及"微批處理 (譯註: mini-batch)"。(後者是經過 Storm Trident 實現)
咱們在 Google 雲上,組建 30 臺機器總計 120Core 的集羣,用來測量 Flink 和 Storm 對兩個不一樣程序的吞吐量。 第一個程序是並行流式 grep 任務,它在流中搜索包含與正則表達式匹配的字符串的事件。grep 應用程序具有的特徵可以讓 grep 很是容易作到並行處理,而且基於流分區進行伸縮。
在 Flink 集羣上,咱們能夠看到 Flink 每核每秒平均有 150 萬條記錄的持續吞吐量,這使 Flink 集羣總吞吐量達到每秒 1.82 億記錄。Flink 的計算延遲爲零,由於做業不涉及網絡,也不涉及微批處理。而當打開 Flink 的容錯機制,並設定每 5 秒作一次快照,能夠看到的是 Flink 吞吐量有輕微下降(小於 2%)。能夠說,Flink 優秀的容錯機制並不會引入任何計算延遲。
在 Storm 集羣上,當咱們關閉記錄確認機制(即沒有任何數據準確性保證),Storm 處理吞吐能力是每核每秒約 82000 條記錄,99% 的處理延遲在 10 毫秒之內,所以整個 Storm 集羣的總吞吐量爲每秒 57 萬條記錄。當啓用記錄確認(即保證數據至少處理一次,at-least-once)時,Storm 的吞吐量降至每核每秒 4700 條記錄,同時 Storm 的延遲也增長到 30-120 毫秒。 接下來,咱們使用 Storm Trident,其微批量大小爲 200000 個元組。 Trident 實現了每核每秒 75000 條記錄的吞吐量(集羣總吞吐量與 Storm 原生處理機制在關閉容錯機制狀況下總體吞吐量大體相同)。然而,這個集羣吞吐性能是以 3000 毫秒的延遲(99% 的百分位數是 3000ms)爲代價換來的。
咱們看到 Flink 的吞吐量比 Trident 高出 20 倍以上,吞吐量比 Storm 高 300 倍,在如此高吞吐狀況下,Flink 還保證了計算延遲幾乎爲零。另外,咱們還看到,Flink 規避了微批處理模型,所以 Flink 的高吞吐量並不會以犧牲延遲爲代價 。 Flink 能夠將 Source 節點和 Sink 節點連接 (Chain) 在一塊兒,從而將數據在 Flink 內部傳遞優化爲在單個 JVM 裏面交換下數據記錄的句柄而已。
以後,咱們還進行了以下實驗,將計算集羣核心數量從 40 個擴展到 120 個。由於 Grep 程序是一個易於並行處理的邏輯,所以全部框架處理能力理論上都可以作到線性擴展。如今讓咱們再作一個稍加不一樣的實驗,它按數據業務主鍵執行流分組,從而實現經過網絡對數據流進行混洗 (Shuffle)。一樣,咱們仍然在 30 臺機器的集羣中運行此做業,集羣硬件系統配置與之前徹底相同。Flink 集羣的吞吐能力以下,當關閉快照檢查點是每核每秒大約 720000 條記錄,當打開快照檢查點後降至 690000 條記錄每秒。 請注意,Flink 在每一個檢查點均備份全部 Operator 的狀態,而 Storm 則徹底不支持這種功能。 此示例中的狀態相對較小(狀態主要是計數和摘要,每一個檢查點每一個運算符的數量小於 1MB)。 Storm 在打開記錄確認狀況下,具備每核心每秒約 2600 條記錄的吞吐能力。
延遲
一個大數據系統可否處理大規模數據量確定相當重要。 但在流式處理系統中,另一個特別重要的點在於計算延遲。 對於欺詐檢測或 IT 安全等應用程序,在毫秒級別可以進行事件處理意味着能夠避免業務損失,一套流式處理系統最低只能優化到 100 毫秒的延遲一般意味着前述問題只能在業務損失發生的過後才能發現,而此時的問題發現對於咱們避免業務損失實際上意義已經不大了。
當應用程序開發人員評估一套流式處理系統性能延遲時,他們一般須要一個底層處理系統告之他們延遲分佈狀況。咱們設計一個實驗,測量業務主鍵聚合場景下做業的延遲分佈狀況,該做業因爲存在主鍵聚合,所以須要流式系統內部數據跨網絡混洗。下圖顯示了延遲分佈狀況,包括延遲中位數、延遲第 90% 位數、第 95% 分位數、第 99% 分位數(所謂第 99% 分位數的 50 毫秒延遲,意味着 99%的元素延遲不超過 50 毫秒)。
值得注意的是,Flink 在以最大吞吐量運行時,其處理中值延遲爲 26 毫秒,第 99 百分位延遲爲 51 毫秒,這意味着 99%的延遲都低於 51 毫秒。 當咱們打開 Flink 的檢查點機制(打開 exactly-once 的狀態更新保證)並無增長明顯的延遲。但此時,咱們確實看處處於較高百分位數的延遲增長,有觀察到的延遲大約爲 150 毫秒。這類狀況主要緣由是流在對齊所消耗的延遲,此時的 Operator 在等待接收全部輸入的 Barrier(譯註: 關於 Barrier 部分,請參考 https://ci.apache.org/projects/flink/flink-docs-master/internals/stream_checkpointing.html 這篇文章)。Storm 具備很是低的中值延遲(1 毫秒),而且第 99 百分位延遲也是 51 毫秒。
對於大多數應用程序而言,重要的是可以在可接受的延遲中維持較高吞吐量,延遲的具體需求取決於特定應用程序的業務要求。 在 Flink 中,用戶可使用稱之爲 Buffer Timeout 的機制來調整延遲。爲了提升性能,Flink 的 Operator 在將數據發送到下一個 Operator 以前會將數據暫存在緩衝區。經過指定緩衝區超時時間,例如設定 10 毫秒,咱們能夠告訴 Flink 當面臨 1) 緩衝區已滿 2)10 毫秒已過 的狀況下發送當前緩衝區全部的數據。 一般來講設定一個較低的緩衝區超時間將優化流式處理的延遲,但隨之而來的是會下降相應的計算吞吐量。 在上面的實驗中,咱們將 Flink 緩衝區超時設置爲 50 毫秒,這解釋了爲何第 99 百分位的是 50 毫秒。
咱們再進一步解釋下延遲是如何影響 Flink 中的吞吐量。由於設定較低的延遲時間將不可避免地意味着緩存數據的減小,所以必然會產生必定的吞吐量成本。 下圖顯示了不一樣緩衝區超時時間設置下的 Flink 吞吐量狀況。 該實驗再次使用流記錄分組聚合的做業。
若是指定緩衝區超時時間爲零,處理的記錄會當即轉發到下游的 Operator 而不會進行緩衝。 如此的延遲優化,Flink 能夠實現 0 毫秒的中值延遲,以及 99% 延遲在 20 毫秒如下。固然,隨之帶來相應的吞吐量是每核每秒 24500 記錄處理能力。當咱們增長緩衝區超時時間,咱們會看到延遲增長,吞吐量會同時增長,直到達到吞吐量峯值,緩衝區填充速度超過緩衝區超時到期時間。例如,設置 50 毫秒的緩衝區超時時間,Flink 系統將達到每核每秒 750000 條記錄的峯值吞吐量,99% 的處理延遲在 50 毫秒如下。
咱們的最後一個實驗開始測試作快照檢查點機制的正確性保證以及故障恢復的開銷。咱們須要運行一個須要強一致性的流式程序,並按期殺死工做節點。
這個實驗的測試程序受到網絡安全 / 入侵檢測等用例的啓發,並使用規則來檢查事件序列的有效性(例如,身份驗證令牌,登陸,服務交互)。該程序從 Kafka 並行地讀取事件流,並經過生成一些實體標識(例如,IP 地址或用戶 ID)做爲主鍵進行分組。 對於每一個事件,流式處理程序會根據一些業務規則校驗事件的順序性(例如,「服務交互」必須在「登陸」以前)。 對於亂序,或者說無效的事件序列,程序會發布警報。若是沒有 exactly-once 的語義保證,人爲製造的故障將直接產生無效的事件序列並致使程序發佈錯誤警報。
一樣,咱們在一個 30 節點的集羣中運行這個程序,其中「YARN chaos monkey」進程每 5 分鐘將隨機殺死一個的 YARN 容器。 咱們保留備用 worker(即 Flink 中的 TaskManagers),這樣系統能夠在發生故障後當即獲取到新資源並運行做業,而無需等待 YARN 啓動新的容器。接着,Flink 將從新啓動失敗的 worker 並在後臺將其加入到 Flink 調度集羣中,以確保備用 worker 始終可用。
爲了保證可以模擬出咱們期待的效果,咱們開發了併發的數據生成器,這些生成器將以每核每秒 30000 的速率生成數據,並將數據推送到 Kafka。 下圖顯示了數據生成器的速率(紅線),以及從 Kafka 讀取事件並使用規則驗證事件序列的 Flink 做業的吞吐量(藍線)。
在 dataArtisans 公司,咱們正在研究 Flink 流處理的幾個重大功能,並但願很快將它們做爲下一個 Flink 版本的一部分提供。(譯註: 這篇文章寫於 2015 年,所以下面做者提到的 Flink Feature 實際上已經所有實現)。
如今,Flink 的主節點(稱爲 JobManager)是單點故障。 咱們正在引入具備備用主節點的主高可用性,該節點使用 Apache Zookeeper 進行主 / 備用協調。
咱們正在向 Flink 添加按事件時間處理亂序事件的能力,即建立記錄時的時間戳而不是處理時的時間戳,以及 Watermark 的引入。
咱們正在開發一個徹底從新設計的管理接口,該接口提供用戶能夠在運行時觀察底層運行細節,並獲取統計信息,例如累加器 (accumulators)。 若是您對此感興趣並但願瞭解有關 Apache Flink™,Google Cloud Dataflow 以及其餘技術和實際用例的更多信息,請註冊 Flink Forward 2015。
陳守元(花名:巴真)阿里巴巴產品專家。阿里巴巴實時計算團隊產品負責人,2010 年畢業即加入阿里集團參與淘寶數據平臺建設,近 10 年的大數據從業經驗,開源項目 Alibaba DataX 發起人,當前負責阿里實時計算產品 Flink 的規劃與設計,致力於推進 Flink 成爲下一代大數據處理標準。
原文連接:
https://data-artisans.com/blog/high-throughput-low-latency-and-exactly-once-stream-processing-with-apache-flink