實時流式計算系統中的幾個陷阱

file
隨着諸如Apache Flink,Apache Spark,Apache Storm之類的開源框架以及諸如Google Dataflow之類的雲框架的增多,建立實時數據處理做業變得很是容易。這些API定義明確,而且諸如Map-Reduce之類的標準概念在全部框架中都遵循幾乎類似的語義。數據庫

可是,直到今天,實時數據處理領域的開發人員都在爲該領域的某些特性而苦苦掙扎。所以,他們在不知不覺中建立了一條路徑,該路徑致使了應用程序中至關常見的錯誤。服務器

讓咱們看一下在設計實時應用程序時可能須要克服的一些陷阱。網絡

活動時間

源生成數據的時間戳稱爲「 事件時間」,而應用程序處理數據的時間戳稱爲「 處理時間」。在實時數據流應用程序中,最多見的陷阱是沒法區分這些時間戳。併發

讓咱們詳細說明一下。框架

因爲諸如代理中的GC較高或太多數據致使背壓之類的多個問題,數據隊列易出現延遲。我將事件表示爲(E,P),其中E是事件時間戳(HH:MM:SS格式),P是處理時間戳。在理想世界中,E == P,但這在任何地方都不會發生。分佈式

假設咱們收到如下數據函數

('05:00:00','05:00:02'),('05:00:01','05:00:03'),('05:00:01','05:00: 03'),('05:00:01','05:00:05'),
('05:00:02','05:00:05'),('05:00:02',' 05:00:05')

如今,咱們假設有一個程序能夠計算每秒接收到的事件數。根據事件時間,程序返回微服務

[05:00:00,05:00:01)= 1 
[05:00:01,05:00:02)= 3 
[05:00:02,05:00:03)= 2

可是,基於處理時間,輸出爲工具

[5時○○分00秒,5點00分01秒)= 0 
[5點00分01秒,5點00分02秒)= 0 
[5點00分02秒,5時00分03秒)= 1 
[05:00: 03,05:00:04)= 2 
[05:00:04,05:00:05)= 0 
[05:00:05,05:00:06)= 3

如您所見,這兩個都是徹底不一樣的結果。設計

數據流中異常的延遲

大多數實時數據應用程序使用來自分佈式隊列的數據,例如Apache Kafka,RabbitMQ,Pub / Sub等。隊列中的數據由其餘服務生成,例如消費者應用程序的點擊流或數據庫的日誌。

問題隊列容易受到延遲的影響。即便在幾十毫秒內,生成的事件也可能到達您的工做中,或者在最壞的狀況下可能會花費一個多小時(極高的背壓)。因爲如下緣由,數據可能會延遲:

  • kafka上的高負載
  • 生產者在其服務器中緩衝數據
  • 因爲應用程序中的背壓,消耗速度慢

假設數據將永遠不會延遲是一個巨大陷阱。開發人員應始終具備測量數據延遲的工具。例如,在Kafka,您應該檢查偏移量滯後。

您還應該監視做業中的背壓以及延遲(即事件時間與處理時間之間的差)。沒有這些將致使數據意外丟失,例如10分鐘。時間窗口彷佛沒有數據,而且窗口顯示10分鐘。以後,其指望值將是預期值的兩倍。

Joins

在批處理數據處理系統中,將兩個數據集合並起來比較簡單。在流處理世界中,狀況變得有些麻煩。

//數據集的格式爲(時間戳,鍵,值)
//數據組1 (05:00: 
00,A,值A),
(05:00: 01,B,值B),(05:00: 04,C,值C),(05:00:04,D,值D)
//數據流2 
(05:00:00,A,值A'),(05:00:02,B,值B' ),
(05:00:00,C,值C')

file

如今,咱們將兩個數據流都放在它們的Key上。爲簡單起見,咱們將進行內部聯接。

Key A — 值A和值A'都同時到達。所以,咱們能夠輕鬆地將它們組合爲一個函數併發出輸出

Key B — 值B比值B`早1秒。所以,咱們須要在數據流1上等待至少1秒鐘,才能使鏈接正常工做。所以,您須要考慮如下內容-

  • 那一秒鐘的數據將存儲在哪裏?
  • 若是1秒不是固定的延遲,而且在最壞的狀況下不規則地增長到10分鐘怎麼辦?

Key C —值C比值C'晚4秒鐘到達。這與之前相同,可是如今您在數據流1和2中都具備不規則的延遲,而且沒有固定的模式將其值設爲1。

Key D —值D到達,可是沒有觀察到值D'。考慮如下-

  • 您要等多久才能得到價值D`?
  • 若是值D`能夠從至少5秒到接近1小時的任什麼時候間出現,該怎麼辦?
  • 若是這是一個外部聯接,而您必須決定什麼時候單獨發出值D,該怎麼辦?
  • 若是在前一種狀況下,在發出值D 1分鐘後到達值D`,該怎麼辦?

file

以上全部問題的答案將取決於您的用例。重要的是要考慮全部這些問題,而不是忽略流系統的複雜性。

必定要注意 不要回避這些問題

配置

在標準微服務中,配置位於做業內部或數據庫中。您能夠在數據流應用程序中執行相同的操做。可是,在繼續使用此方法以前,您須要考慮如下事項。

您將多久訪問一次配置?

若是須要爲每一個事件訪問配置,而且事件數量不少(超過一百萬RPM),那麼您也能夠嘗試其餘方法。一種是將配置存儲在做業狀態中。這可使用狀態處理在Flink和Spark中完成。可使用文件讀取器或Kafka中的其餘流以狀態填充該配置。

在流處理世界中,針對每一個事件進行數據庫調用可能會使您的應用程序變慢並致使背壓。選擇是使用快速數據庫,仍是經過在應用程序內部存儲狀態來消除網絡調用。

您的配置有多大?

若是配置很大,則僅當配置能夠拆分到多個服務器時才應使用應用程序內狀態,例如,一個配置爲每一個用戶保留一些閾值。能夠基於用戶ID密鑰將這樣的配置拆分到多臺計算機上。這有助於減小每臺服務器的存儲量。

若是沒法在節點之間拆分配置,請首選數據庫。不然,全部數據將須要路由到包含配置的單個服務器,而後再次從新分發。惟一包含配置的服務器充當該方案的瓶頸。

file

設計實時數據流應用程序彷佛很容易,可是開發人員會犯不少上述錯誤,特別是若是它們來自微服務領域。

重要的部分是瞭解數據流的基礎知識以及如何處理單個流,而後轉處處理多個聯接,實時配置更新等的複雜應用程序。

更多實時數據分析相關博文與科技資訊,歡迎關注 「實時流式計算」

file

相關文章
相關標籤/搜索