
概述
Kafka被廣泛認(rèn)為是一種強(qiáng)大的消息總線,可以可靠地傳遞事件流,是流式處理系統(tǒng)的理想數(shù)據(jù)來源。流式處理系統(tǒng)通常是指一種處理實(shí)時數(shù)據(jù)流的計算系統(tǒng),能夠?qū)?shù)據(jù)進(jìn)行實(shí)時的處理和分析,并根據(jù)需要進(jìn)行相應(yīng)的響應(yīng)和操作。與傳統(tǒng)的批處理系統(tǒng)不同,流式處理系統(tǒng)能夠在數(shù)據(jù)到達(dá)時立即進(jìn)行處理,這使得它們特別適合需要實(shí)時響應(yīng)的應(yīng)用程序,例如實(shí)時監(jiān)控和警報、實(shí)時推薦、實(shí)時廣告投放等。
Kafka的設(shè)計使其成為流式處理系統(tǒng)的理想數(shù)據(jù)源,因?yàn)樗哂懈咄掏铝?、低延遲和可靠性,并且能夠輕松地擴(kuò)展以處理大量數(shù)據(jù)。許多基于Kafka的流式處理系統(tǒng),如Apache Storm、Apache Spark Streaming、Apache Flink和Apache Samza等,已經(jīng)成功地應(yīng)用于各種不同的場景中。
Kafka的流式處理類庫提供了一種簡單而強(qiáng)大的方式來處理實(shí)時數(shù)據(jù)流,并將其作為Kafka客戶端庫的一部分提供。這使得開發(fā)人員可以在應(yīng)用程序中直接讀取、處理和生成事件,而無需依賴外部的處理框架。Kafka的流式處理類庫提供了許多有用的功能,如窗口化處理、狀態(tài)存儲和流處理拓?fù)錁?gòu)建等,使得開發(fā)人員能夠輕松地構(gòu)建強(qiáng)大的流式處理應(yīng)用程序。
隨著Kafka的流行和流式處理技術(shù)的發(fā)展,流式處理系統(tǒng)已經(jīng)成為數(shù)據(jù)處理的一個重要領(lǐng)域,并且在越來越多的應(yīng)用場景中得到廣泛應(yīng)用。Kafka的流式處理類庫為開發(fā)人員提供了一種強(qiáng)大的工具來處理實(shí)時數(shù)據(jù)流,并從中提取有用的信息,是構(gòu)建復(fù)雜的流式處理系統(tǒng)的理想選擇。
什么是流式處理
流式處理是一種編程范式,用于實(shí)時處理一個或多個事件流。事件流是無邊界數(shù)據(jù)集的抽象表示,它們是無限和持續(xù)增長的,隨著時間的推移,新的記錄會不斷加入進(jìn)來。
與批處理不同,流式處理可以對事件流進(jìn)行實(shí)時處理,而不需要等待所有數(shù)據(jù)都可用之后再進(jìn)行處理。這使得流式處理非常適用于需要實(shí)時響應(yīng)的業(yè)務(wù)場景,如可疑交易警報、網(wǎng)絡(luò)警報、實(shí)時價格調(diào)整和包裹跟蹤等。
流式處理具有以下幾個特征:
-
有序:事件流中的數(shù)據(jù)記錄是按照它們發(fā)生的時間順序排列的。這意味著流式處理可以按照事件發(fā)生的順序進(jìn)行處理,從而得出正確的結(jié)果。
-
不可變:事件流中的數(shù)據(jù)記錄是不可變的,即一旦記錄被創(chuàng)建,它就不能被修改。這使得流式處理更容易實(shí)現(xiàn),因?yàn)樗恍枰紤]并發(fā)修改問題。
-
可重播:事件流中的數(shù)據(jù)記錄可以被重復(fù)處理,從而使得流式處理具有容錯性。如果處理過程中發(fā)生了錯誤,可以重新處理相同的數(shù)據(jù)記錄,直到得到正確的結(jié)果。
-
低延遲:流式處理具有較低的延遲,即處理事件流的時間很短,通常在毫秒或微秒級別。這使得流式處理非常適用于需要實(shí)時響應(yīng)的業(yè)務(wù)場景。
-
高吞吐量:流式處理具有較高的吞吐量,即能夠處理大量的數(shù)據(jù)記錄。這使得流式處理非常適用于處理大規(guī)模的數(shù)據(jù)集。
-
不依賴于具體框架或API:流的定義不依賴于任何特定的框架、API或特性,只要從一個無邊界的數(shù)據(jù)集中讀取數(shù)據(jù)并進(jìn)行處理,就可以進(jìn)行流式處理。這使得流式處理具有較大的靈活性和可擴(kuò)展性。
流式處理是一種能夠?qū)崟r處理無邊界數(shù)據(jù)集的編程范式,具有有序、不可變、可重播、低延遲、高吞吐量和靈活性等特點(diǎn),非常適用于需要實(shí)時響應(yīng)的業(yè)務(wù)場景。
流式處理的一些概念
時間
時間或許就是流式處理最為重要的概念,也是最讓人感到困惑的。在討論分布式系統(tǒng)時,該如何理解復(fù)雜的時間概念? 在流式處理里,時間是一個非常重要的概念,因?yàn)榇蟛糠至魇綉?yīng)用的操作都是基于時間窗口的。事
- 事件時間(Event Time):事件實(shí)際發(fā)生的時間。這是最重要的時間概念,大部分流式應(yīng)用都是基于事件時間來進(jìn)行窗口操作和聚合的。
- 日志追加時間(Log Append Time):事件被寫入Kafka的時間。這種時間主要是Kafka內(nèi)部使用的,和流式應(yīng)用無太大關(guān)系。
- 處理時間(Processing Time):應(yīng)用程序收到事件并開始處理的時間。這種時間不可靠,可能會產(chǎn)生不同的值,所以流式應(yīng)用很少使用它。
推薦讀者閱讀 Justin Sheehy 的論文《There is No Now》來深入理解這些時間概念,特別是在分布式系統(tǒng)環(huán)境下的復(fù)雜性。
在流式系統(tǒng)中,如果生產(chǎn)者出現(xiàn)網(wǎng)絡(luò)問題導(dǎo)致離線幾個小時,然后大量數(shù)據(jù)涌入,這會給系統(tǒng)帶來很大困難。因?yàn)榇蟛糠謹(jǐn)?shù)據(jù)的事件時間已經(jīng)超出我們設(shè)定的窗口范圍,無法進(jìn)行正常的聚合計算。
為了解決這個問題,流式系統(tǒng)提供了幾種機(jī)制:
- 丟棄超出窗口的數(shù)據(jù):簡單但會導(dǎo)致數(shù)據(jù)損失
- 調(diào)整窗口:擴(kuò)大窗口以包含更多數(shù)據(jù),但窗口范圍變大會影響計算精度
- 重發(fā)數(shù)據(jù):生產(chǎn)者將離線期間的數(shù)據(jù)重新發(fā)送,系統(tǒng)會進(jìn)行補(bǔ)充計算以產(chǎn)生正確的結(jié)果
- 水印(Watermark):允許指定數(shù)據(jù)遲到的最大時間,系統(tǒng)會等待水印時間之內(nèi)的數(shù)據(jù)到達(dá)后開始計算并輸出結(jié)果。水印機(jī)制可以有效解決數(shù)據(jù)遲到的問題 while 保證結(jié)果的準(zhǔn)確性。
所以,在設(shè)計流式應(yīng)用時需要考慮這些時間概念,特別要考慮數(shù)據(jù)遲到和離線的情況,并選擇合適的機(jī)制來處理,保證系統(tǒng)的準(zhǔn)確性。
狀態(tài)
- 單純處理單個事件很簡單,但涉及多個事件時需要跟蹤更多信息,這些信息被稱為“狀態(tài)”。
- 狀態(tài)通常存儲在應(yīng)用程序的本地變量中,如散列表。但本地狀態(tài)存在丟失風(fēng)險,重啟后狀態(tài)變化,需持久化最近狀態(tài)并恢復(fù)。
- 本地狀態(tài)或內(nèi)部狀態(tài):只能被單個應(yīng)用程序?qū)嵗L問,使用內(nèi)嵌數(shù)據(jù)庫維護(hù),速度快但受限于內(nèi)存大小。許多設(shè)計將數(shù)據(jù)拆分到子流使用本地狀態(tài)處理。
- 外部狀態(tài):使用外部數(shù)據(jù)存儲維護(hù),如NoSQL系統(tǒng)Cassandra。大小無限制,多個應(yīng)用實(shí)例可訪問,但增加延遲和復(fù)雜度。大部分流式處理應(yīng)用避免外部存儲,或緩存在本地減少交互以降低延遲,引入內(nèi)外狀態(tài)一致性問題
流和表的二元性
- 表是記錄的集合,具有主鍵和schema定義的屬性,記錄可變,查詢可得某時刻狀態(tài),如CUSTOMERS_CONTACTS表獲取所有客戶聯(lián)系信息。但表無歷史信息。
- 流是事件序列,每個事件是變更。表是多變更結(jié)果的當(dāng)前狀態(tài)。表和流是同一硬幣兩面:世界變化,關(guān)注變更事件或當(dāng)前狀態(tài)。支持兩種方式的系統(tǒng)更強(qiáng)大。
- 將表轉(zhuǎn)為流需捕獲表變更事件(insert、update、delete),如CDC解決方案發(fā)送變更到Kafka流式處理。
- 將流轉(zhuǎn)為表需應(yīng)用流所有變更以改變狀態(tài),在內(nèi)存、內(nèi)部狀態(tài)存儲或外部數(shù)據(jù)庫創(chuàng)建表,遍歷流所有事件逐個改變狀態(tài),得到某時間點(diǎn)狀態(tài)的表。
假設(shè)有一個鞋店,某零售活動可以使用一個事件流來表示:
“紅色、藍(lán)色和綠色鞋子到貨”
“藍(lán)色鞋子賣出”
“紅色鞋子賣出”
“藍(lán)色鞋子退貨”
“綠色鞋子賣出”
如果想知道現(xiàn)在倉庫里還有哪些庫存,或者到目前為止賺了多少錢,需要對視圖進(jìn)行物化。
應(yīng)用流中所有變更事件來改變狀態(tài)并建立表,表轉(zhuǎn)流需要捕獲表上的變更事件并發(fā)送到流進(jìn)行后續(xù)流式處理。表代表某時刻的狀態(tài),流代表變更,二者相互轉(zhuǎn)化,支持兩種方式的系統(tǒng)更強(qiáng)大
時間窗口
針對流的時間窗口操作主要有以下幾種類型:
- 窗口大小:5分鐘、15分鐘、1天等,大小影響變更檢測速度和平滑度。窗口越小,變更檢測越快但噪聲也越大;窗口越大,變更越平滑但延遲也越嚴(yán)重。
- 窗口移動頻率(“移動間隔”):5分鐘平均值每分鐘變化一次或每秒變化一次或每新事件變化一次。移動間隔等于窗口大小為“滾動窗口”,隨每記錄移動為“滑動窗口”。
- 窗口可更新時間:計算00:00-00:05平均值,1小時后00:02事件,是否更新00:00-00:05窗口結(jié)果?可定義時間段內(nèi)事件添加對應(yīng)時間片段,如4小時內(nèi)更新,否則忽略。
- 窗口與時間對齊或不對齊:5分鐘窗口每分鐘移動,第一個片00:00-00:05,第二個00:01-00:06;或應(yīng)用任時啟動,第一個片03:17-03:22?;瑒哟翱陔S新記錄移動,永不與時間對齊。
窗口大小影響操作結(jié)果的靈敏度和平滑度,移動間隔決定結(jié)果更新頻率,可更新時間決定遲到事件是否參與運(yùn)算。窗口可與時間對齊或不對齊。
滑動窗口隨每新事件移動,滾動窗口按預(yù)定間隔移動,但兩者移動間隔都不超過窗口大小。滾動窗口移動間隔與窗口大小相等時,相鄰窗口沒有重疊;滑動窗口移動間隔小于窗口大小時,相鄰窗口有重疊。
【滾動窗口和跳躍窗口的區(qū)別】
流式處理的設(shè)計模式
單個事件處理
處理單個事件是流式處理最基本的模式。這個模式也叫 map 或 filter 模式,因?yàn)樗?jīng)常被用于過濾無用的事件或者用于轉(zhuǎn)換事件
map 這個術(shù)語是從 Map-Reduce 模式中來的,map階段轉(zhuǎn)換事件,reduce 階段聚合轉(zhuǎn)換過的事件)。
讀取流事件,修改并寫到其他流。如讀取日志流,ERROR級別消息寫高優(yōu)先級流,其他寫低優(yōu)先級流;或JSON轉(zhuǎn)Avro格式。無需維護(hù)狀態(tài),易恢復(fù)錯誤或負(fù)載均衡。
【單事件處理拓?fù)洹?br>
這種模式可以使用一個生產(chǎn)者和一個消費(fèi)者來實(shí)現(xiàn).
使用本地狀態(tài)
多數(shù)流處理應(yīng)用聚合信息,如每天最高最低股票價和移動平均值。需維護(hù)流狀態(tài),如保存最小最大值和新值比較。可通過本地狀態(tài)實(shí)現(xiàn),每操作一組聚合,如下圖。Kafka分區(qū)確保同代碼事件同分區(qū)。每個應(yīng)用實(shí)例獲取分配分區(qū)事件,維護(hù)一組股票代碼狀態(tài)。
多階段處理和重分區(qū)
本地狀態(tài)適組內(nèi)聚合,要全信息結(jié)果如每日前10股票需兩階段:第一階段每個實(shí)例計算每股漲跌,寫單分區(qū)新主題;第二階段單應(yīng)用實(shí)例讀取新主題找前10股。新主題只股票摘要,流量小,單實(shí)例足以。更多步驟亦如MapReduce多reduce步驟,每個步驟應(yīng)用隔離。流處理框架可多步驟一應(yīng)用,框架調(diào)度每個步驟哪個應(yīng)用實(shí)例運(yùn)行。
【包含本地狀態(tài)和重分區(qū)步驟的拓?fù)洹?/p>
使用外部查找——流和表的連接
【使用外部數(shù)據(jù)源的流式處理】
外部查找會帶來嚴(yán)重的延遲
為了獲得更好的性能和更強(qiáng)的伸縮性,需要將數(shù)據(jù)庫的信息緩存到流式處理應(yīng)用程序里。不過,要管理好這個緩存也是一個挑戰(zhàn)。
比如,如何保證緩存里的數(shù)據(jù)是最新的?如果刷新太頻繁,那么仍然會對數(shù)據(jù)庫造成壓力,緩存也就失去了作用。如果刷新不及時,那么流式處理中所用的數(shù)據(jù)就會過時。
如果能夠捕捉數(shù)據(jù)庫的變更事件,并形成事件流,流式處理作業(yè)就可以監(jiān)聽事件流,并及時更新緩存。捕捉數(shù)據(jù)庫的變更事件并形成事件流,這個過程被稱為 CDC——變更數(shù)據(jù)捕捉(Change Data Capture)。如果使用了 Connect,就會發(fā)現(xiàn),有一些連接器可以用于執(zhí)行CDC 任務(wù),把數(shù)據(jù)庫表轉(zhuǎn)成變更事件流。
這樣就擁有了數(shù)據(jù)庫表的私有副本,一旦數(shù)據(jù)庫發(fā)生變更,用戶會收到通知,并根據(jù)變更事件更新私有副本里的數(shù)據(jù),如圖
【連接流和表的拓?fù)洌恍枰獠繑?shù)據(jù)源】
流與流的連接
在 Streams 中,上述的兩個流都是通過相同的鍵來進(jìn)行分區(qū)的,這個鍵也是用于連接兩個流的鍵。這樣一來,user_id:42 的點(diǎn)擊事件就被保存在點(diǎn)擊主題的分區(qū) 5 上,而所有 user_id:42 的搜索事件被保存在搜索主題的分區(qū) 5 上。Streams 可以確保這兩個主題的分區(qū) 5 的事件被分配給同一個任務(wù),這個任務(wù)就會得到所有與 user_id:42 相關(guān)的事件。
Streams 在內(nèi)嵌的 RocksDB 里維護(hù)了兩個主題的連接時間窗口,所以能夠執(zhí)行連接操作
亂序的事件
處理亂序和遲到事件的要點(diǎn):
- 識別亂序事件:檢查事件時間,與當(dāng)前時間比較,超出時間窗口視為亂序或遲到。
- 規(guī)定時間窗口重排亂序事件:如3小時內(nèi)事件重排,3周外事件丟棄。
- 重排時間窗口內(nèi)亂序事件的能力:流處理與批處理不同,無“重新運(yùn)行昨日作業(yè)”概念,須同時處理亂序與新事件。
- 更新結(jié)果的能力:如結(jié)果在數(shù)據(jù)庫,用put或update更新;如郵件發(fā)送結(jié)果,更新方式需巧妙。
- 支持時間獨(dú)立事件的框架:如Dataflow和Streams維護(hù)多個聚合時間窗口,更新事件,且可配置窗口大小。窗口越大,本地狀態(tài)內(nèi)存需求越高。
- Streams API聚合結(jié)果寫入主題,常為壓縮日志主題,每個鍵只保留最新值。如果聚合窗口結(jié)果需更新,直接為窗口寫入新結(jié)果,覆蓋前結(jié)果。
處理亂序和遲到事件需要:
- 識別時間窗口外的事件,丟棄或特殊處理
- 為時間窗口內(nèi)的亂序事件定義重排窗口,在該窗口內(nèi)重排亂序事件
- 具有在定義的時間窗口內(nèi)重排亂序事件并更新結(jié)果的能力
- 選擇支持時間獨(dú)立事件和本地狀態(tài)管理的流框架,如Dataflow或Streams
- 將更新后的聚合結(jié)果直接 overwrite,使用壓縮日志主題避免結(jié)果主題無限增長
事件的亂序和遲到是流處理的常見場景,但又不太適合批處理的重新計算方式。定義多個時間窗口以管理歷史狀態(tài),重排時間窗口內(nèi)亂序事件,直接覆蓋更新結(jié)果可以有效解決此類問題。
Streams提供的本地狀態(tài)管理、時間窗口支持和壓縮日志主題寫入使其可以高效處理亂序和遲到事件。通過配置不同時間窗口,開發(fā)人員可以實(shí)現(xiàn)不同粒度的狀態(tài)管理和事件重排。
事件亂序和遲到帶來的挑戰(zhàn)在于歷史狀態(tài)的管理和結(jié)果的更新,Streams等流框架的出現(xiàn)使開發(fā)人員無需過于關(guān)注這些底層問題,可以專注于流處理應(yīng)用的業(yè)務(wù)邏輯。
重新處理
重處理事件的兩種模式:
- 改進(jìn)流處理應(yīng)用,新版本應(yīng)用處理同事件流,生成新結(jié)果,比較兩版本結(jié)果,時間點(diǎn)切換客戶端新結(jié)果流。
- 現(xiàn)有應(yīng)用有缺陷,修復(fù)后重處理事件流重新計算結(jié)果。
第一種模式實(shí)現(xiàn):
- 新版本應(yīng)用作為新消費(fèi)者群組
- 從輸入主題第一個偏移量開始讀取事件,獲得自己輸入流事件副本
- 檢查結(jié)果流,新版本應(yīng)用趕上進(jìn)度,切換客戶端應(yīng)用新結(jié)果流
第二種模式挑戰(zhàn): - 重置應(yīng)用到輸入流起點(diǎn)重新處理,重置本地狀態(tài),避免混淆兩版本結(jié)果
- 可能需清理前輸出流
- 盡管Streams提供重置應(yīng)用狀態(tài)工具,有條件運(yùn)行兩個應(yīng)用生成兩個結(jié)果流更安全,可以比較不同版本結(jié)果,無數(shù)據(jù)丟失或清理引入錯誤風(fēng)險
重處理事件模式需要:
- 事件流長期在可擴(kuò)展數(shù)據(jù)存儲,如Kafka
- 運(yùn)行不同版本應(yīng)用作為不同消費(fèi)者群組,各自處理事件流并生成結(jié)果
- 新版本應(yīng)用從頭讀取事件,建立自己的輸入流副本和結(jié)果,避免影響當(dāng)前版本
- 比較不同版本結(jié)果,確定切換時機(jī),小心切換客戶端到新結(jié)果流
- 可選清理現(xiàn)有結(jié)果和狀態(tài),使用重置工具小心操作,或采用并行模式避免清理
事件流的長期保留為重新處理事件和 AB 測試不同版本應(yīng)用程序提供了可能。重置當(dāng)前運(yùn)行的應(yīng)用程序存在一定風(fēng)險,并行運(yùn)行多個版本的應(yīng)用程序可以最大限度減小風(fēng)險。
無論采用何種模式,重新處理事件都需要小心謹(jǐn)慎的計劃與執(zhí)行。不同版本應(yīng)用程序生成的結(jié)果流比較可以讓我們清楚地知道新的版本是否達(dá)到了預(yù)期的改進(jìn),這為重新處理事件和發(fā)布提供了依據(jù)。
Streams 的消費(fèi)者群組管理和工具支持使其在重新處理事件和 AB 測試場景下性能卓越。通過將不同版本應(yīng)用加入不同消費(fèi)者群組,各自處理事件流并生成獨(dú)立結(jié)果,再小心migrate客戶端,這是一種較為安全可靠的重新處理事件模式。
事件流的長期保留和可靠的狀態(tài)管理是重新處理事件的基石。AB 測試不同版本應(yīng)用程序也可借此機(jī)制實(shí)現(xiàn),這為流式應(yīng)用的持續(xù)優(yōu)化和演化提供了可能。文章來源:http://www.zghlxwxcb.cn/news/detail-689441.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-689441.html
到了這里,關(guān)于Apache Kafka - 流式處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!