您好,登錄后才能下訂單哦!
Flink Table的三種Sink模式分別是什么,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
作為計(jì)算引擎 Flink 應(yīng)用的計(jì)算結(jié)果總要以某種方式輸出,比如調(diào)試階段的打印到控制臺(tái)或者生產(chǎn)階段的寫到數(shù)據(jù)庫。而對(duì)于本來就需要在 Flink 內(nèi)存保存中間及最終計(jì)算結(jié)果的應(yīng)用來說,比如進(jìn)行聚合統(tǒng)計(jì)的應(yīng)用,輸出結(jié)果便是將內(nèi)存中的結(jié)果同步到外部。就 Flink Table/SQL API 而言,這里的同步會(huì)有三種模式,分別是 Append、Upsert 和 Retract。實(shí)際上這些輸出計(jì)算結(jié)果的模式并不限于某個(gè)計(jì)算框架,比如 Storm、Spark 或者 Flink DataStream 都可以應(yīng)用這些模式,不過 Flink Table/SQL 已有完整的概念和內(nèi)置實(shí)現(xiàn),更方便討論。
相信接觸過 Streaming SQL 的同學(xué)都有了解或者聽過流表二象性,簡單來說流和表是同一事實(shí)的不同表現(xiàn),是可以相互轉(zhuǎn)換的。流和表的表述在業(yè)界不盡相同,筆者比較喜歡的一種是: 流體現(xiàn)事實(shí)在時(shí)間維度上的變化,而表則體現(xiàn)事實(shí)在某個(gè)時(shí)間點(diǎn)的視圖。如果將流比作水管中流動(dòng)的水,那么表將是杯子里靜止的水。
將流轉(zhuǎn)換為表的方法對(duì)于大多數(shù)讀者都不陌生,只需將聚合統(tǒng)計(jì)函數(shù)應(yīng)用到流上,流很自然就變?yōu)楸恚ㄖ档米⒁獾氖?,F(xiàn)link 的 Dynamic Table 和表的定義有細(xì)微不同,這將在下文講述)。比如對(duì)于一個(gè)計(jì)算 PV 的簡單流計(jì)算作業(yè),將用戶瀏覽日志數(shù)據(jù)流安 url 分類統(tǒng)計(jì),變成 (url, views)
這樣的一個(gè)表。然而對(duì)于如何將表轉(zhuǎn)換成流,讀者則未必有這么清晰的概念。
假設(shè)一個(gè)典型的實(shí)時(shí)流計(jì)算應(yīng)用的工作流程可以被簡化為下圖:
其中很關(guān)鍵的一點(diǎn)是 Transformation 是否聚合類型的計(jì)算。若否,則輸出結(jié)果依然是流,可以很自然地使用原本流處理的 Sink(與外部系統(tǒng)的連接器);若是,則流會(huì)轉(zhuǎn)換為表,那么輸出的結(jié)果將是表,而一個(gè)表的輸出通常是批處理的概念,不能直接簡單地用流處理的 Sink 來表達(dá)。
這時(shí)有個(gè)很樸素的想法是,我們能不能避免批處理那種全量的輸出,每次只輸出表的 diff,也就是 changelog。這也是表轉(zhuǎn)化為流的方法: 持續(xù)觀察表的變化,并將每個(gè)變化記錄成日志輸出。因此,流和表的轉(zhuǎn)換可以以下圖表示:
其中表的變化具體可以分為 INSERT
、UPDATE
和 DELETE
三類,而 Flink 根據(jù)這些變化類型分別總結(jié)了三種結(jié)果的輸出模式。
模式 | INSERT | UPDATE | DELETE |
---|---|---|---|
Append | 支持 | 不支持 | 不支持 |
Upsert | 支持 | 支持 | 支持 |
Retract | 支持 | 支持 | 支持 |
通常來說 Append 是最容易實(shí)現(xiàn)但功能最弱的,Retract 是最難實(shí)現(xiàn)而功能最強(qiáng)的。下文分別談?wù)勅N模式的特點(diǎn)和應(yīng)用場景。
Append 是最為簡單的輸出模式,只支持追加結(jié)果記錄的操作。因?yàn)榻Y(jié)果一旦輸出以后便不會(huì)再有變更,Append 輸出模式的最大特性是不可變性(immutability),而不可變性最令人向往的優(yōu)勢(shì)便是安全,比如線程安全或者 Event Sourcing 的可恢復(fù)性,不過同時(shí)也會(huì)給業(yè)務(wù)操作帶來限制。通常來說,Append 模式會(huì)用于寫入不方便做撤回或者刪除操作的存儲(chǔ)系統(tǒng)的場景,比如 Kafka 等 MQ 或者打印到控制臺(tái)。
在實(shí)時(shí)聚合統(tǒng)計(jì)中,聚合統(tǒng)計(jì)的結(jié)果輸出是由 Trigger 決定的,而 Append-Only 則意味著對(duì)于每個(gè)窗口實(shí)例(Pane,窗格)Trigger 只能觸發(fā)一次,則就導(dǎo)致無法在遲到數(shù)據(jù)到達(dá)時(shí)再刷新結(jié)果。通常來說,我們可以給 Watermark 設(shè)置一個(gè)較大的延遲容忍閾值來避免這種刷新(再有遲到數(shù)據(jù)則丟棄),但代價(jià)是卻會(huì)引入較大的延遲。
不過對(duì)于不涉及聚合的 Table 來說,Append 輸出模式是非常好用的,因?yàn)檫@類 Table 只是將數(shù)據(jù)流的記錄按時(shí)間順序排在一起,每條記錄間的計(jì)算都是獨(dú)立的。值得注意的是,從 DataFlow Model 的角度來看未做聚合操作的流不應(yīng)當(dāng)稱為表,但是在 Flink 的概念里所有的流都可以稱為 Dynamic Table。筆者認(rèn)為這個(gè)設(shè)計(jì)也有一定的道理,原因是從流中截取一段出來依然可以滿足表的定義,即”某個(gè)時(shí)間點(diǎn)的視圖”,而且我們可以爭辯說不聚合
也是一種聚合函數(shù)。
Upsert 是 Append 模式的升級(jí)版,支持 Append-Only 的操作和在有主鍵的前提下的 UPDATE 和 DELETE 操作。Upsert 模式依賴業(yè)務(wù)主鍵來實(shí)現(xiàn)輸出結(jié)果的更新和刪除,因此非常適合 KV 數(shù)據(jù)庫,比如
HBase、JDBC 的 TableSink 都使用了這種方式。
在底層,Upsert 模式下的結(jié)果更新會(huì)被翻譯為 (Boolean, ROW) 的二元組。其中第一個(gè)元素表示操作類型,true
對(duì)應(yīng) UPSERT
操作(不存在該元素則 INSERT
,存在則 UPDATE
),false
對(duì)應(yīng) DELETE
操作,第二個(gè)元素則是操作對(duì)應(yīng)的記錄。如果結(jié)果表本身是 Append-Only 的,第一個(gè)元素會(huì)全部為 true
,而且也無需提供業(yè)務(wù)主鍵。
Upsert 模式是目前來說比較實(shí)用的模式,因?yàn)榇蟛糠謽I(yè)務(wù)都會(huì)提供原子或復(fù)合類型的主鍵,而在支持 KV 的存儲(chǔ)系統(tǒng)也非常多,但要注意的是不要變更主鍵,具體原因會(huì)在下一節(jié)談到。
Retract 是三種輸出模式中功能最強(qiáng)大但實(shí)現(xiàn)也最復(fù)雜的一種,它要求目標(biāo)存儲(chǔ)系統(tǒng)可以追蹤每個(gè)條記錄,而且這些記錄至少在一定時(shí)間內(nèi)都是可以撤回的,因此通常來說它會(huì)自帶系統(tǒng)主鍵,不必依賴于業(yè)務(wù)主鍵。然而由于大數(shù)據(jù)存儲(chǔ)系統(tǒng)很少有可以精確到一條記錄的更新操作,因此目前來說至少在 Flink 原生的 TableSink 中還沒有能在生產(chǎn)環(huán)境中滿足這個(gè)要求的。
不同于 Upsert 模式更新時(shí)會(huì)將整條記錄重新輸出,Retract 模式會(huì)將更新分成兩條表示增減量的消息,一條是 (false, OldRow)
的撤回(Retract)操作,一條是 (true, NewRow)
的積累(Accumulate)操作。這樣的好處是,在主鍵出現(xiàn)變化的情況下,Upsert
輸出模式無法撤回舊主鍵的記錄,導(dǎo)致數(shù)據(jù)不準(zhǔn)確,而 Retract
模式則不存在這個(gè)問題。
舉個(gè)例子,假設(shè)我們將電商訂單按照承運(yùn)快遞公司進(jìn)行分類計(jì)數(shù),有如下的結(jié)果表。
那么如果原本一單為中通的快遞,后續(xù)更新為用順豐發(fā)貨,對(duì)于 Upsert 模式會(huì)產(chǎn)生 (true, (順豐, 4))
這樣一條 changelog,但中通的訂單數(shù)沒有被修正。相比之下,Retract 模式產(chǎn)出 (false, (中通, 1))
和 (true, (順豐, 1))
兩條數(shù)據(jù),則可以正確地更新數(shù)據(jù)。
Flink Table Sink 的三種模式本質(zhì)上是如何監(jiān)控結(jié)果表并產(chǎn)生 changelog,這可以應(yīng)用于所有需要將表轉(zhuǎn)為流的場景,包括同一個(gè) Flink 應(yīng)用的不同表間的聯(lián)動(dòng)。三種模式中 Append 模式只支持表的 INSERT
,最為簡單;Upsert 模式依賴業(yè)務(wù)主鍵提供 INSERT
、UPDATE
和 DELETE
全部三類變更,比較實(shí)用;Retract 模式同樣支持三類變更且不要求業(yè)務(wù)主鍵,但會(huì)將 UPDATE
翻譯為舊數(shù)據(jù)的撤回和新數(shù)據(jù)的累加,實(shí)現(xiàn)上比較復(fù)雜。
看完上述內(nèi)容,你們掌握Flink Table的三種Sink模式分別是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。