|0x00 從流批一體誕生的必然性說(shuō)起
通常來(lái)講,數(shù)據(jù)倉(cāng)庫(kù)的建設(shè),都是以離線作為主要的密報(bào),下游的應(yīng)用,不論是報(bào)表還是接口,所提供的數(shù)據(jù)也大多是T-1時(shí)效性。
但伴隨著業(yè)務(wù)的變化,當(dāng)離線做到?jīng)]什么可以繼續(xù)做的時(shí)候,實(shí)時(shí)就會(huì)被拿出來(lái),作為新一個(gè)階段的目標(biāo)進(jìn)行攻克。
在流批一體建設(shè)之前,這種實(shí)時(shí)訴求通常會(huì)開(kāi)發(fā)成分鐘級(jí)的任務(wù),通過(guò)近實(shí)時(shí)的方案來(lái)解決業(yè)務(wù)的問(wèn)題,但分鐘級(jí)會(huì)帶來(lái)諸如任務(wù)過(guò)多、資源擠占較大、無(wú)法支持復(fù)雜邏輯等問(wèn)題。
因此專門支持實(shí)時(shí)計(jì)算的框架,比如早期的Storm,能夠嘗試從純實(shí)時(shí)的角度解決業(yè)務(wù)問(wèn)題,就被拿出來(lái)作為嘗試。然而Storm的局限性也很大,因?yàn)槟菚?huì)的任務(wù)開(kāi)發(fā)只能通過(guò)Java的方式來(lái)進(jìn)行,與Hive所推崇的純SQL方案相比,上手難度大了不少,同時(shí)兩套代碼的邏輯幾乎沒(méi)有可比性,這種方案也就一直沒(méi)有什么聲音。
盡管實(shí)時(shí)技術(shù)有各種缺陷,但作為一種能夠很容易講清楚價(jià)值的項(xiàng)目,同時(shí)又非常便于向上匯報(bào)的技術(shù)方案,實(shí)時(shí)技術(shù)還是被或多或少的做了起來(lái)。在大多數(shù)的公司里,實(shí)時(shí)和離線就會(huì)有不同的團(tuán)隊(duì)進(jìn)行維護(hù),或者是同一個(gè)團(tuán)隊(duì),但分成不同的項(xiàng)目來(lái)執(zhí)行。這個(gè)階段,優(yōu)先高效的把業(yè)務(wù)做起來(lái),哪怕場(chǎng)景再簡(jiǎn)單,但能夠證明實(shí)時(shí)有價(jià)值和前景,這個(gè)階段的目標(biāo)就算完成了。
以上的各種方案,難免會(huì)帶來(lái)三個(gè)特別難以解決的問(wèn)題:
(1)數(shù)據(jù)的口徑上,實(shí)時(shí)和離線很容易不統(tǒng)一;
(2)數(shù)據(jù)模型的規(guī)范上,實(shí)時(shí)和離線也往往是分開(kāi)建設(shè);
(3)即便是同一種口徑和同一種規(guī)范,實(shí)時(shí)和離線也要分成兩套代碼來(lái)維護(hù)。
這三個(gè)問(wèn)題短時(shí)間內(nèi)會(huì)被高速發(fā)展掩蓋掉,但當(dāng)業(yè)務(wù)對(duì)實(shí)時(shí)的訴求越來(lái)越多、壓力越來(lái)越大的時(shí)候,口徑和代碼的不統(tǒng)一,就會(huì)越來(lái)越成為阻礙敏捷開(kāi)發(fā)的障礙,需要有方案進(jìn)行解決。
后來(lái)Flink出現(xiàn)了,帶來(lái)了流批一體的全新方案,這個(gè)問(wèn)題便出現(xiàn)了解決的曙光,這也比較接近我們對(duì)于實(shí)時(shí)計(jì)算的理想方案,因?yàn)槠湟饬x堪比Hive,也成為了各個(gè)大廠面試的標(biāo)配問(wèn)題。
然而,僅僅學(xué)會(huì)Flink是不夠的,因?yàn)榱髋惑w帶來(lái)的并不僅僅是技術(shù)方案或者是框架的改變,同樣帶來(lái)了數(shù)據(jù)模型的改變,這就要求我們從數(shù)據(jù)模型上,而不是技術(shù)方案上,來(lái)制定我們的實(shí)時(shí)方案。
|0x01 實(shí)時(shí)的數(shù)據(jù)模型方案是怎樣的
那么我們?nèi)绾卫斫狻皩?shí)時(shí)數(shù)據(jù)模型”這件事情呢?
通常而言,我們關(guān)心的內(nèi)容,包括如下幾個(gè)方面:
(1)實(shí)時(shí)數(shù)據(jù)源與離線數(shù)據(jù)源存在差異,導(dǎo)致相同的字段,取值或者類型會(huì)存在不相等的情況;
(2)實(shí)時(shí)和離線由于底層執(zhí)行機(jī)制的不同,通常需要維護(hù)兩套代碼,會(huì)帶來(lái)諸如口徑不統(tǒng)一、質(zhì)量檢測(cè)難的問(wèn)題;
(3)產(chǎn)品邏輯變化較快時(shí),離線模型修改相對(duì)容易,但實(shí)時(shí)模型需要考慮壓測(cè)、削峰、重啟等技術(shù)問(wèn)題,維護(hù)成本非常高昂。
數(shù)據(jù)倉(cāng)庫(kù)之所以能夠普及并被業(yè)務(wù)接受,正是因?yàn)槠淠P湍軌蚱帘蔚舻讓硬町惖膯?wèn)題,并且有相對(duì)可靠的數(shù)據(jù)質(zhì)量監(jiān)控方法,并且變更成本非常低。而實(shí)時(shí)數(shù)倉(cāng)如果想要替代掉離線數(shù)倉(cāng),以上的問(wèn)題通常是需要一些模型設(shè)計(jì)甚至是平臺(tái)工具的來(lái)解決,這些問(wèn)題解決的重要性,并不比Flink弱。
我們先從比較可控的模型層面說(shuō)起。
在離線的概念里,數(shù)倉(cāng)模型設(shè)計(jì)成了DWD/DWS/ADS三個(gè)層級(jí),原本的概念是DWD面向事實(shí)表的構(gòu)建,DWS面向公共指標(biāo)的統(tǒng)一,ADS負(fù)責(zé)靈活的口徑變化問(wèn)題。
在離線的概念里,DWD/DWS/ADS三個(gè)層級(jí)需要保留,但負(fù)責(zé)的目標(biāo)會(huì)有一些變化,同時(shí)還需要增加存儲(chǔ)統(tǒng)一層,也就是以TiDB/Holo為代表的數(shù)據(jù)庫(kù),來(lái)承擔(dān)服務(wù)分析一體化的訴求。
讓我們先看DWD層,DWD承擔(dān)了屏蔽實(shí)時(shí)離線鏈路差異的問(wèn)題,最重要的作用是保證表結(jié)構(gòu)的統(tǒng)一及字段內(nèi)容的對(duì)齊。DWD最重要的意義,是保證離線表和實(shí)時(shí)表,其表結(jié)構(gòu)和字段概念是相同的。
為什么這么強(qiáng)調(diào)?試想一下,在離線場(chǎng)景下,我們可以在DWD上靈活的增加各種統(tǒng)計(jì)標(biāo)簽,或者是將維度退化到事實(shí)表,都是一些left join或者是服務(wù)端直接打標(biāo)可以解決的事情。但在實(shí)時(shí)場(chǎng)景下,這會(huì)變成多流join或者是緩存等更復(fù)雜的技術(shù)場(chǎng)景,導(dǎo)致這些信息并不能有效的記錄到DWD,因此DWD的設(shè)計(jì)就要產(chǎn)生一些變化,有一些內(nèi)容在實(shí)時(shí)場(chǎng)景下無(wú)法準(zhǔn)確記錄,這一類信息需要標(biāo)識(shí)到對(duì)應(yīng)的字段描述上,下游使用時(shí)才不會(huì)出錯(cuò)。
同時(shí),實(shí)時(shí)和離線存儲(chǔ)數(shù)據(jù)的介質(zhì),也必然有一些區(qū)別。例如離線可以存在HDFS上,實(shí)時(shí)則可能視情況保存在數(shù)據(jù)庫(kù)、HDFS甚至是內(nèi)存中,這時(shí)候?qū)τ谧侄胃袷?、讀取方式都會(huì)有差異,設(shè)計(jì)表時(shí)其約束條件也會(huì)更多。
因而,DWD更多承擔(dān)了邏輯統(tǒng)一的職責(zé),依舊以事實(shí)表為基礎(chǔ),但約束條款要比離線更多。
再看一下DWS層,離線上DWS是負(fù)責(zé)口徑統(tǒng)一的重要一環(huán),將通用的維度和口徑計(jì)算方法抽象出現(xiàn),以提供跨數(shù)據(jù)域的靈活使用。但在實(shí)時(shí)場(chǎng)景下,這一類的維護(hù)收益通常都比較低,不僅因?yàn)閷?shí)時(shí)只看當(dāng)天的數(shù)據(jù),也是因?yàn)閷?shí)時(shí)本身的維度難度就較大,多一層模型其收益會(huì)急速下降,因而大多數(shù)時(shí)候會(huì)忽略掉DWS的建設(shè),ADS直接引用DWD進(jìn)行統(tǒng)計(jì)。
然而,DWS畢竟存儲(chǔ)的內(nèi)容要比DWD少很多,因此如果計(jì)算資源瓶頸非常明顯,或者是業(yè)務(wù)場(chǎng)景不需要分析實(shí)時(shí)明細(xì)數(shù)據(jù)的情況下,或者是DWD的下游引用過(guò)多時(shí),DWS可以承擔(dān)削峰的重任,通過(guò)減少數(shù)據(jù)量以應(yīng)對(duì)大促等場(chǎng)景,還是有一定意義的。
接下來(lái)就是最重要的ADS層,在這一層上,邏輯統(tǒng)一、口徑統(tǒng)一、大促削峰在前置模型上都得到了一定程度的解決,ADS則像離線一樣承擔(dān)了應(yīng)對(duì)需求變化的重任。
但ADS所面臨的情況和離線還是有所不同的,因?yàn)锳DS的任務(wù)啟動(dòng),不僅要啟動(dòng)一個(gè)離線的跑批任務(wù),還要同時(shí)啟動(dòng)一個(gè)實(shí)時(shí)的流式任務(wù),而ADS往往會(huì)同時(shí)統(tǒng)計(jì)離線+實(shí)時(shí)的結(jié)果,以應(yīng)對(duì)同比、環(huán)比等場(chǎng)景。
這時(shí)候很多具體Case要具體分析了,因?yàn)樘囟▓?chǎng)景的坑會(huì)非常多。例如最常見(jiàn)的“同比”,要對(duì)比今年和去年的結(jié)果變化,離線往往會(huì)統(tǒng)計(jì)分小時(shí)的結(jié)果,但實(shí)時(shí)會(huì)累計(jì)起始時(shí)刻到當(dāng)期時(shí)刻的結(jié)果,因而當(dāng)一個(gè)小時(shí)沒(méi)有結(jié)束的時(shí)候,這個(gè)同比的波動(dòng)變化會(huì)非常大,給人一種“數(shù)據(jù)是錯(cuò)誤的”印象,新手很容易踩這個(gè)坑,從而被業(yè)務(wù)質(zhì)疑。
因此,針對(duì)累計(jì)統(tǒng)計(jì)指標(biāo),從代碼設(shè)計(jì)上就要考慮到這種情況,都根據(jù)時(shí)間字段統(tǒng)計(jì)起始到當(dāng)前時(shí)刻的結(jié)果的,在代碼邏輯上會(huì)要求一些統(tǒng)計(jì)技巧。
很多時(shí)候,因?yàn)闃I(yè)務(wù)指標(biāo)變化太快,改實(shí)時(shí)代碼是來(lái)不及的,這時(shí)候一部分的工作量甚至需要報(bào)表工具的數(shù)據(jù)集來(lái)解決,改動(dòng)查詢sql,要比改動(dòng)任務(wù)來(lái)的快捷多了。但這部分的能力,其實(shí)是依賴于存儲(chǔ)工具的,個(gè)人認(rèn)為可以分到存儲(chǔ)統(tǒng)一層來(lái)解決。
最后是存儲(chǔ)統(tǒng)一層,因?yàn)橐恍┨厥獾膱?chǎng)景,比如實(shí)時(shí)分析明細(xì)數(shù)據(jù),或者是不確定時(shí)間周期的多天統(tǒng)計(jì)結(jié)果,如果依賴Flink SQL來(lái)解決是有些不現(xiàn)實(shí)的,因而這部分的壓力需要數(shù)據(jù)庫(kù)來(lái)承擔(dān)。
簡(jiǎn)單講,就是將明細(xì)做輕度的匯總后,直接寫(xiě)到數(shù)據(jù)庫(kù),實(shí)時(shí)更新,下游自定義條件,并直接讀庫(kù)統(tǒng)計(jì)結(jié)果。這種場(chǎng)景既要求數(shù)據(jù)庫(kù)有OLAP的計(jì)算能力,也要有OLTP的穩(wěn)定特點(diǎn),因而TiDB和Holo這一類HTAP的引擎就變得非常重要。
|0x02 實(shí)時(shí)模型對(duì)于開(kāi)發(fā)工具有哪些要求
因?yàn)槎嗔藢?shí)時(shí)的部分,因此過(guò)去面向離線的開(kāi)發(fā)工具,也需要有一些特定的改造,以適應(yīng)實(shí)時(shí)的開(kāi)發(fā)和運(yùn)維訴求。
對(duì)于開(kāi)發(fā)工具而言,其目標(biāo)集中在四個(gè)場(chǎng)景上:元數(shù)據(jù)定義與獲取、數(shù)據(jù)建模、開(kāi)發(fā)與測(cè)試、運(yùn)維與監(jiān)控。
首先講元數(shù)據(jù)定義與獲取,F(xiàn)link通常對(duì)接能夠支持發(fā)布訂閱的消息流框架,因而其元數(shù)據(jù)并不像表一樣有明確的定義,我們?cè)讷@取消息流的數(shù)據(jù)格式和定義時(shí),就需要專門的系統(tǒng)來(lái)承載。同時(shí),離線和實(shí)時(shí)不同的地方,在于離線僅需要統(tǒng)計(jì)任務(wù)完成后的一些執(zhí)行情況,而實(shí)時(shí)則需要將日志量的趨勢(shì)展示出來(lái)。
其次講數(shù)據(jù)建模,因?yàn)榻5睦碚撘呀?jīng)穩(wěn)定了有些年頭了,絕大多數(shù)場(chǎng)景下都是按照既定的方案來(lái)執(zhí)行。過(guò)去離線當(dāng)?shù)罆r(shí),規(guī)范執(zhí)行的弱一些不是什么大問(wèn)題,但流批一體當(dāng)?shù)赖哪甏?,?guī)范是需要強(qiáng)約束的,這就對(duì)了開(kāi)發(fā)工具提出了一定的要求,是否能夠從平臺(tái)層面上對(duì)規(guī)范進(jìn)行內(nèi)置,并以此來(lái)約束開(kāi)發(fā)的同學(xué),降低不規(guī)范模型對(duì)后期維護(hù)帶來(lái)的壓力。
這種建模能力的代表有兩種,一種是規(guī)范表的命名,填寫(xiě)相應(yīng)的分層+主題域+數(shù)據(jù)域+統(tǒng)計(jì)刷新方式,從源頭上規(guī)范表的目標(biāo)和作用;一種是規(guī)范指標(biāo)的定義和使用,例如原子指標(biāo)還是派生指標(biāo),統(tǒng)計(jì)周期多少,業(yè)務(wù)限定用語(yǔ)如何規(guī)范,統(tǒng)計(jì)粒度怎么填寫(xiě)。
在實(shí)際開(kāi)發(fā)中,通過(guò)工具的限制,如果規(guī)范可以做的好,代碼是可以自動(dòng)生成出來(lái)的。當(dāng)然,以上的功能,都屬于通過(guò)犧牲開(kāi)發(fā)效率,來(lái)提升數(shù)據(jù)質(zhì)量的范疇,使用時(shí)需要根據(jù)團(tuán)隊(duì)的情況來(lái)限定。
再次是開(kāi)發(fā)和測(cè)試,這是平臺(tái)提供的最重要的能力。在開(kāi)發(fā)層面,就是代碼的預(yù)編譯能力+發(fā)布功能。預(yù)編譯不僅要檢查代碼的邏輯是否正確,同時(shí)對(duì)于代碼中依賴的其他數(shù)據(jù)源,獲取到的元數(shù)據(jù)信息是否準(zhǔn)確,至少字段的命名不會(huì)有大的問(wèn)題。當(dāng)代碼預(yù)編譯通過(guò),發(fā)布上線后,還需要檢測(cè)當(dāng)前是否有資源支持任務(wù)啟動(dòng),并且上游的消息隊(duì)列是否是啟動(dòng)的狀態(tài)。
實(shí)時(shí)的測(cè)試一直都是比較大的問(wèn)題,它不像離線可以啟動(dòng)一個(gè)SQL任務(wù)看看結(jié)果,實(shí)時(shí)在每個(gè)階段的輸入和輸出,是需要通過(guò)平臺(tái)支持的日志打印功能來(lái)進(jìn)行輔助的。很多時(shí)候我們會(huì)新建一個(gè)測(cè)試專用的topic來(lái)測(cè)試結(jié)果,但對(duì)于流量較大的線上任務(wù)而言,這種方式無(wú)法像離線區(qū)分Dev環(huán)境一樣,能夠?qū)Y源進(jìn)行隔離,因而如果能夠支持圈定數(shù)據(jù)的輸入和打印輸出,對(duì)于測(cè)試的效率而言無(wú)疑是最佳的。
最后要提到的是運(yùn)維與監(jiān)控能力。運(yùn)維能力是指根據(jù)輸入的RPS,或者是cu使用情況,或者是任務(wù)的整體延遲,提供相應(yīng)的參數(shù)調(diào)優(yōu)能力,通過(guò)參數(shù)來(lái)調(diào)整任務(wù)的執(zhí)行情況。并且能夠根據(jù)以上指標(biāo)的變化,自定義相應(yīng)的閾值,提供相應(yīng)的告警能力,通過(guò)短信或者是消息工具的方式觸達(dá)任務(wù)維護(hù)者。
實(shí)時(shí)與離線有一些不同的是,離線可以通過(guò)增加一個(gè)監(jiān)控節(jié)點(diǎn)的方式,通過(guò)group by判斷數(shù)據(jù)是否重復(fù),而實(shí)時(shí)任務(wù)則非常依賴Flink自身的一致性能力,因而發(fā)現(xiàn)和解決問(wèn)題的成本更高。
其實(shí)做到運(yùn)維這個(gè)環(huán)節(jié),對(duì)人的要求其實(shí)是更高的。因?yàn)榱髋惑w在運(yùn)維上會(huì)帶來(lái)一個(gè)好處,即實(shí)時(shí)任務(wù)和離線任務(wù)能夠錯(cuò)峰執(zhí)行,實(shí)時(shí)在白天壓力大,而離線在晚上壓力大。但同樣的,這種方式對(duì)于維護(hù)者而言更加痛苦,因?yàn)椴粌H晚上要熬夜值班,白天同樣不能休息,在大促期間甚至需要輪班來(lái)維護(hù)任務(wù),可以說(shuō)是“匯報(bào)一時(shí)爽,痛苦長(zhǎng)相伴”。
從遠(yuǎn)處來(lái)看,流任務(wù)和批任務(wù),在自身的機(jī)制上就存在非常大的差異,批程序面上的是特定時(shí)間內(nèi)相對(duì)靜態(tài)的數(shù)據(jù),而流程序處理的則是change-log,雖然有可能數(shù)據(jù)在表結(jié)構(gòu)層面,通過(guò)數(shù)據(jù)模型的設(shè)計(jì)來(lái)保持一致,但是在語(yǔ)義層面,其根本還是不一樣的。這一點(diǎn)可能是最制約批流一體發(fā)展的問(wèn)題,也是最難實(shí)現(xiàn)統(tǒng)一或者永遠(yuǎn)也不可能統(tǒng)一的。
綜上,對(duì)于實(shí)時(shí)模型,開(kāi)發(fā)工具需要將監(jiān)控實(shí)時(shí)部分的能力進(jìn)行補(bǔ)全,就像DWD層需要分別維護(hù)實(shí)時(shí)和離線兩套架構(gòu)一樣,開(kāi)發(fā)工具也需要分別維護(hù)兩套架構(gòu)的結(jié)果,因而現(xiàn)階段的實(shí)時(shí)開(kāi)發(fā),還做不到降低維護(hù)和開(kāi)發(fā)的成本,只能減輕其中部分環(huán)節(jié)的工作量。
|0xFF 流批一體的價(jià)值取決于業(yè)務(wù)方
以上講了很長(zhǎng)時(shí)間的實(shí)時(shí)模型,但從實(shí)際的效果上看,業(yè)務(wù)并不會(huì)感知到多么明顯的技術(shù)變化,相反會(huì)有一種“面子工程”的感覺(jué)在里面。
當(dāng)然,我并不否認(rèn)實(shí)時(shí)的價(jià)值,在“搜廣推”這三個(gè)技術(shù)占主導(dǎo)的領(lǐng)域內(nèi),作用還是很大的。但實(shí)時(shí)畢竟要比離線的內(nèi)容,更加的難以理解,出現(xiàn)問(wèn)題的排查成本也更高。這種復(fù)雜性使得我們?cè)趹?yīng)對(duì)變化時(shí),往往做不出有效的應(yīng)對(duì),就會(huì)變得特別被動(dòng)。
因而,說(shuō)一句事后的話,就是“實(shí)時(shí)的價(jià)值取決于業(yè)務(wù)方,而不是技術(shù)方”。只有業(yè)務(wù)對(duì)實(shí)時(shí)痛點(diǎn)強(qiáng)烈的場(chǎng)景下,我們做如此復(fù)雜的研究和應(yīng)對(duì),才能體現(xiàn)出自己的價(jià)值,更多的時(shí)候,是在“王婆賣瓜,自賣自夸”。有這種投入,還不如多招幾個(gè)分析師更靠譜和實(shí)在。
本人之前的文章《天下數(shù)據(jù),唯快不破》,重點(diǎn)強(qiáng)調(diào)了一個(gè)“快”字。但“天下熙熙皆為利來(lái),天下攘攘皆為利往”,這個(gè)快更多的是在講應(yīng)對(duì)“變化”的快,而不是“技術(shù)”自己的快。
所以,為了以后的職業(yè)發(fā)展,我們要跟進(jìn)實(shí)時(shí)技術(shù)的變化,但從自身的工作角度出發(fā),如何應(yīng)對(duì)業(yè)務(wù)的變化,才是自己要關(guān)心的課題。