![]() |
博主歷時(shí)三年精心創(chuàng)作的《大數(shù)據(jù)平臺(tái)架構(gòu)與原型實(shí)現(xiàn):數(shù)據(jù)中臺(tái)建設(shè)實(shí)戰(zhàn)》一書現(xiàn)已由知名IT圖書品牌電子工業(yè)出版社博文視點(diǎn)出版發(fā)行,點(diǎn)擊《重磅推薦:建大數(shù)據(jù)平臺(tái)太難了!給我發(fā)個(gè)工程原型吧!》了解圖書詳情,京東購書鏈接:https://item.jd.com/12677623.html,掃描左側(cè)二維碼進(jìn)入京東手機(jī)購書頁面。 |
目前看,F(xiàn)link 的 “維表 Join” 主要就三種實(shí)現(xiàn)方式,叫法可能會(huì)有細(xì)微差別,以下是我是用更直白的語言總結(jié)的稱謂:
- 直連外部數(shù)據(jù)庫進(jìn)行關(guān)聯(lián)
- 將維表加載到內(nèi)存中關(guān)聯(lián)
- 基于維表變更日志的關(guān)聯(lián)
這些 Join 方案具體會(huì)使用到 Flink 的 Lookup Join、Temporal Join 等相關(guān)機(jī)制,所以在研究維表 Join 方案前,應(yīng)先補(bǔ)齊這部分的知識(shí),具體可參考本文末給出的本博客相關(guān)系列文章。
網(wǎng)上有這樣一篇文章《Flink DataStream 關(guān)聯(lián)維表實(shí)戰(zhàn)》,總結(jié)得已經(jīng)非常好了,我們不打算重新發(fā)明輪子,本文更像是一篇學(xué)習(xí)筆記。
1. 直連外部數(shù)據(jù)庫進(jìn)行關(guān)聯(lián)
顧名思義,這種方式就不需要再解釋了。Flink 中的 Lookup Join 就是應(yīng)用在這種場(chǎng)景下的。我們來分析一下這種關(guān)聯(lián)方式的優(yōu)缺點(diǎn),應(yīng)該說它的優(yōu)缺點(diǎn)是非常鮮明的:
-
優(yōu)點(diǎn)
- 實(shí)現(xiàn)簡(jiǎn)單 => 是所有管理方式中最容易實(shí)現(xiàn)的
- 實(shí)時(shí)性高 => 維表發(fā)生變更后能立即反映到關(guān)聯(lián)的結(jié)果集中
- 不占用內(nèi)存 ( 能夠關(guān)聯(lián)較大的維表 ) => 維度數(shù)據(jù)是直接從數(shù)據(jù)庫查詢獲得,不會(huì)占用 Flink 工作節(jié)點(diǎn)的內(nèi)存,這也就意味著能關(guān)聯(lián)較大的維表
-
缺點(diǎn)
- 數(shù)據(jù)庫負(fù)載高 ( 容易成為性能瓶頸 ) => 流上的 Join 是持續(xù)查詢,對(duì)維表數(shù)據(jù)庫的訪問會(huì)異常頻繁,極易導(dǎo)致性能問題
-
適用場(chǎng)景:
-
數(shù)據(jù)流量不大的流
-
項(xiàng)目初期的原型快速實(shí)現(xiàn)
-
鑒于直連外部數(shù)據(jù)庫進(jìn)行關(guān)聯(lián)對(duì)數(shù)據(jù)庫的壓力過大,有一些優(yōu)化措施可以適當(dāng)緩解一下數(shù)據(jù)庫的壓力,具體地說主要是“異步查詢“和”引入緩存“兩種優(yōu)化措施,而上面說的默認(rèn)實(shí)現(xiàn)方式是”同步查詢“,這樣,在該選型下,總共有三種細(xì)分方案。
1.1. 同步查詢
沒有任何特別之處,默認(rèn)情況下,使用客戶端查詢數(shù)據(jù)庫都是同步模式。同步模式的性能問題會(huì)尤為突出,沒有做任何優(yōu)化。
1.2. 異步查詢
要想在 Flink 中異步訪問數(shù)據(jù)庫,首先需要目標(biāo)數(shù)據(jù)庫本身支持異步查詢(提供異步查詢的客戶端、類庫),然后,再基于 Flink 的 Async I/O API 進(jìn)行一層封裝才能實(shí)現(xiàn)異步查詢。異步查詢可以顯著提升查詢的吞吐量,但不能保準(zhǔn)順序性,所以在維度數(shù)據(jù)變更前后有可以會(huì)出現(xiàn)關(guān)聯(lián)了錯(cuò)誤版本的維度數(shù)據(jù)(無序性),通常,維表的變化速率都不會(huì)太快(緩慢變化維度),一般的應(yīng)用是可以接受這種情況的,且流上的數(shù)據(jù)進(jìn)入流計(jì)算引擎時(shí)本身就已經(jīng)有了一定的時(shí)延,所以異步導(dǎo)致的問題基本都是可以忽略不計(jì)的。如果對(duì)關(guān)聯(lián)的時(shí)間尺度要求極高,則應(yīng)考慮”基于維表變更日志的關(guān)聯(lián)“。
1.3. 引入緩存
和 Web 應(yīng)用中引入緩存加速數(shù)據(jù)讀取性能一樣,F(xiàn)link 程序也可以引入緩存實(shí)現(xiàn)同樣的目標(biāo)。這部分的實(shí)現(xiàn)其實(shí)和 Flink 本身的 API 沒有太大關(guān)系,只是運(yùn)行環(huán)境是 Flink 罷了,這個(gè)命題其實(shí)可以改為:在 Java 程序中有沒有好的緩存框架以及如何使用。這一塊可以研究一下 Guava Cache,看上去是目前 Java 平臺(tái)上比較主流的緩存框架了。當(dāng)然,引入專門的分布式緩存基礎(chǔ)設(shè)施也是可考慮的方案之一。
引入緩存的收益是非常明顯的,只是如何保持緩存數(shù)據(jù)和數(shù)據(jù)庫的數(shù)據(jù)一致是比較麻煩的,同異步查詢一樣,如果對(duì)關(guān)聯(lián)的時(shí)間尺度要求極高,在沒有很好的緩存更新策略下,還是應(yīng)考慮”基于維表變更日志的關(guān)聯(lián)“。
2. 將維表加載到內(nèi)存中關(guān)聯(lián)
“將維表加載到內(nèi)存中關(guān)聯(lián)” 像是 “直連外部數(shù)據(jù)庫實(shí)時(shí)關(guān)聯(lián)” 的反向極端,它的優(yōu)缺點(diǎn)也是非常鮮明的:
-
優(yōu)點(diǎn)
- 極致的性能 => 不會(huì)有這種方式更快的關(guān)聯(lián)方式了
- 高吞吐量 => 數(shù)據(jù)駐留內(nèi)存,吞吐量瓶頸只取決于 Flink 集群自身
- 數(shù)據(jù)庫負(fù)載低 => 對(duì)數(shù)據(jù)庫的壓力幾乎可以忽略不計(jì)
-
缺點(diǎn)
- 高內(nèi)存占用 => 占用過多內(nèi)存,不能加載過大,過多的維表
- 實(shí)時(shí)性差 => 源表維度數(shù)據(jù)發(fā)生變更后,內(nèi)存中的數(shù)據(jù)感知不到,只能手動(dòng)觸發(fā)更新或定時(shí)刷新
-
適用場(chǎng)景
- 體量小且?guī)缀醪粫?huì)變更表,例如:字典表
在《Flink DataStream 關(guān)聯(lián)維表實(shí)戰(zhàn)》一文中還詳細(xì)介紹了該方法下的幾種優(yōu)化方案,包括:只加載特定分區(qū)的數(shù)據(jù)緩解內(nèi)存壓力,如何進(jìn)行定時(shí)的數(shù)據(jù)刷新,以及將加載數(shù)據(jù)到內(nèi)存與直連數(shù)據(jù)庫兩種方法結(jié)合起來使用,詳情可參考原文。
3. 基于維表變更日志的關(guān)聯(lián)
基于維表變更日志的關(guān)聯(lián)就是 Flink 的 Temporal Join,所以這種方法會(huì)細(xì)分為:
- 使用基于事件時(shí)間的 Temporal Join 關(guān)聯(lián)維表
- 使用基于處理時(shí)間的 Temporal Join 關(guān)聯(lián)維表
基于事件時(shí)間的維表關(guān)聯(lián),在時(shí)間尺度上是最嚴(yán)格,最準(zhǔn)確的,它能確保關(guān)聯(lián)到事實(shí)表數(shù)據(jù)所代表的事件在發(fā)生時(shí)維表上當(dāng)時(shí)的對(duì)應(yīng)數(shù)據(jù),如果業(yè)務(wù)場(chǎng)景的維表變更速率很快,業(yè)務(wù)上又不容許任何時(shí)間上的錯(cuò)誤關(guān)聯(lián)(例如關(guān)聯(lián)匯率表進(jìn)行匯率換算),則這是唯一的關(guān)聯(lián)方式。
基于處理時(shí)間的 Temporal Join 關(guān)聯(lián)維表在時(shí)效性上其實(shí)也能滿足絕大多數(shù)的場(chǎng)景需求,因?yàn)榇蠖嗟木S表變更速率都不快(緩慢變化維度)?;诨谔幚頃r(shí)間的 Temporal Join 和 直連數(shù)據(jù)庫的 Lookup 非常像,以至于有人錯(cuò)誤地將它們認(rèn)成是同一種關(guān)聯(lián)方式,它們的主要區(qū)別是:Lookup Join 是直連數(shù)據(jù)查詢的,而 “基于處理時(shí)間的 Temporal Join” 是構(gòu)建在 Flink 上的動(dòng)態(tài)表,變更是靠 CDC 實(shí)時(shí)同步的;Lookup Join 需要高頻訪問數(shù)據(jù)庫,對(duì)于數(shù)據(jù)庫會(huì)造成較高的負(fù)載,而“基于處理時(shí)間的 Temporal Join”維表數(shù)據(jù)是在流上,維表變化是通過 CDC 更新的,所以,后者不會(huì)對(duì)維表數(shù)據(jù)庫造成壓力。
-
優(yōu)點(diǎn)
- 實(shí)時(shí)性高 => 尤其基于事件時(shí)間的 Temporal Join,實(shí)時(shí)性和準(zhǔn)確性是最高的
- 數(shù)據(jù)庫負(fù)載低 => 對(duì)數(shù)據(jù)庫的壓力幾乎可以忽略不計(jì)
-
缺點(diǎn)
- 內(nèi)存占用高 => 其內(nèi)存占用沒有“將維表加載到內(nèi)存中關(guān)聯(lián)”那樣高,但是對(duì)于大的維表,為了維持狀態(tài),依然會(huì)占用相當(dāng)可觀的內(nèi)存
-
適用場(chǎng)景
- 對(duì)關(guān)聯(lián)的實(shí)時(shí)性和時(shí)態(tài)上的準(zhǔn)確性要求嚴(yán)格的場(chǎng)景,如:關(guān)聯(lián)匯率表計(jì)算匯率
關(guān)于這種方式的實(shí)現(xiàn)難度其實(shí)還好,主要是前期要積累足夠的知識(shí),包括 Flink CDC, Upsert-Kafka,Temporal Join 等,實(shí)現(xiàn)的代碼并不多,只是知識(shí)密度比較高。
3.1 使用基于事件時(shí)間的 Temporal Join 關(guān)聯(lián)維表
關(guān)于這種實(shí)現(xiàn)方式,請(qǐng)參考本博客另外兩篇文章:
- 《Flink Temporal Join 系列 (1):用 Temporal Table DDL 實(shí)現(xiàn)基于事件時(shí)間的關(guān)聯(lián)》
- 《Flink Temporal Join 系列 (3):用 Temporal Table Function 實(shí)現(xiàn)基于事件時(shí)間的關(guān)聯(lián)》
3.2 使用基于處理時(shí)間的 Temporal Join 關(guān)聯(lián)維表
關(guān)于這種實(shí)現(xiàn)方式,請(qǐng)參考本博客另外兩篇文章:
-
《Flink Temporal Join 系列 (2):用 Temporal Table DDL 實(shí)現(xiàn)基于處理時(shí)間的關(guān)聯(lián)》
-
《Flink Temporal Join 系列 (4):用 Temporal Table Function 實(shí)現(xiàn)基于處理時(shí)間的關(guān)聯(lián)》文章來源:http://www.zghlxwxcb.cn/news/detail-844653.html
參考資料文章來源地址http://www.zghlxwxcb.cn/news/detail-844653.html
- 《Flink DataStream 關(guān)聯(lián)維表實(shí)戰(zhàn)》
到了這里,關(guān)于Flink:維表 Join 難點(diǎn)和技術(shù)方案匯總的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!