對spark2.3.0中Structured Streaming低延遲持續處理模式的介紹

原文鏈接:https://databricks.com/blog/2018/03/20/low-latency-continuous-processing-mode-in-structured-streaming-in-apache-spark-2-3-0.html

在Spark2.0中,Structured Streaming將微批處理模式與其高級API分離開來。原因有兩個:首先,簡化了API的使用,屏蔽了底層的微批處理細節。其次,Structured Streaming允許開發人員將流數據看做一個無界表,並且查詢體驗和靜態表一致。

爲了充分利用這一優勢,在Spark2.3.0中引入一種被稱爲連續模式的可以實現毫秒級延遲的流處理模式。


在本篇文章中,我們會對連續處理模式模型以及優勢進行說明。並且會向開發人員展示如何使用它來編寫具有毫秒級低延遲要求的連續流應用程序。

低延遲場景

假設我們想建立一個實時流處理程序來標記信用卡欺詐交易。在理想的情況下,一旦犯罪分子刷了信用卡,我們就能立即對欺詐行爲進行識別和阻止。但是,又不想讓進行合法交易的用戶感覺到延遲從而影響用戶體驗。所以流數據的端到端處理延遲需要有一個嚴格的上限。考慮到在數據傳輸過程中存在其他延誤,流處理必須在10~20ms時間範圍內實現對每筆交易的欺詐識別。

我們先嚐試利用Structured Streaming構建這個流處理程序。假設我們有一個名爲“isPaymentFlagged” 的函數可以用於判別欺詐交易。爲了儘量減少延遲,我們將使用0秒的處理時間觸發器,即對於每個微批數據Spark需要在獲得時立即啓動處理,從較高的層次來看,查詢看起來像這樣:

payments \
  .filter("isPaymentFlagged(paymentId)") \
  .writeStream \
   {...}
  .trigger(processingTime = "0 seconds") \
  .start()

您可以通過下載並將此示例導入Databricks工作區(使用Databricks Community Edition)來查看完整的代碼。 我們來看看我們得到的端到端延遲。


可以看到Spark處理記錄的時間超過100ms,雖然對於很多應用場景來說100ms已經足夠好了,但是對於上述用例是無法滿足需求的。那麼,新出現的連續流處理能夠解決問題嗎?

payments \
  .filter("isPaymentFlagged(paymentId)") \
  .writeStream \
   {...}
  .trigger(continuous = "5 seconds") \
  .start

現在絕大多數記錄的處理延時被降低到1ms以下-超過兩個數量級的性能提升,且遠低於之前要求的延時範圍。爲了理解爲何微批方式流數據處理有這麼高的延時,以及爲何持續處理模式能夠將延時降到毫秒級別,我們還需要深入瞭解 Structured Streaming流數據處理引擎的細節。

基於微批(Micro-Batch)的流處理

Structured Streaming默認使用微批處理執行模型。 這意味着Spark流式計算引擎會定期檢查流數據源,並對自上一批次結束後到達的新數據執行批量查詢。 在高層次上,它看起來像這樣。


在這個體系結構中,Driver驅動程序通過將記錄偏移量保存到預寫日誌中來對數據處理進度設置檢查點,然後可以使用它來重新啓動查詢。 需要注意的是,爲了獲得確定性的重新執行(deterministic re-executions)和端到端語義,在處理下一個微批數據之前,要將該微批數據中的偏移範圍保存到日誌中。 所以,當前到達的數據需要等待當前的微批處理作業完成,且其中數據的偏移量範圍被計入日誌後,才能在下一個微批作業中得到處理。 在細粒度上,時間線看起來像這樣。



這會導致數據到達和得到處理並輸出結果之間的延時超過100ms。

在之前,用戶只能通過微批處理引擎構建結構化數據的流處理應用,從而可以從Spark SQL的優化工作中受益。在之前,我們能夠在100ms的延時級別實現高吞吐量的流數據處理,在過去的幾年裏,在與數千開發人員和上百個使用案例合作的過程中,我們發現微批的數據延時對於大多數實際的流式工作負載(如ETL和監控)已經足夠了。然而,一些場景確實需要更低的延時,所以我們設計並構建了連續處理模式。

連續處理(Continuous Processing)

在連續處理模式中,Spark不再是啓動週期性任務,而是啓動一系列連續讀取,處理和寫入數據的長時間運行的任務。 在高層次上,設置和記錄級時間線看起來像這些(與上述微量批處理執行圖相對照)。



由於事件在到達時會被立即處理和寫入結果,所以端到端延遲只有幾毫秒。

此外,我們利用著名的Chandy-Lamport算法對查詢進度設置檢查點。 特殊標記的記錄被注入到每個任務的輸入數據流中; 我們將它們稱爲“時間代標記(epoch marker)”,並將它們之間的差距稱爲“時間代(epoch)”。當任務遇到標記時,任務異步報告處理後的最後偏移量給driver。 一旦driver程序接收到寫入接收器的所有任務的偏移量,它就會將它們寫入前述的預寫日誌。 由於檢查點的設置是完全異步的,任務可以不間斷地持續並提供一致的毫秒級延遲。

在Spark2.3.0中,流數據的連續處理模式還是一種實驗性功能,在此模式下支持Structured Streaming所支持的所有流數據源以及DataFrame / Dataset / SQL操作的子集。

具體而言,你可以在滿足以下條件的查詢中設置可選的連續觸發器:

1.從支持的數據源(例如Kafka)讀取數據並寫入支持的接收器(例如Kafka)、內存或者控制檯(數據寫入內存或控制檯便於程序的debug)

2.僅使用map-like操作(例如:select, where, map, flatMap, filter等);

3.除聚合函數外,還有任何SQL函數以及基於當前時間的函數,如current_timestamp()和current_date()。


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