Lambda架構(gòu)已死,基于IOTA模型的“秒算平臺”架構(gòu)實踐
原創(chuàng)【51CTO.com原創(chuàng)稿件】經(jīng)過多年的發(fā)展,從大數(shù)據(jù)1.0的BI/Datawarehouse時代,到大數(shù)據(jù)2.0的Web/App過渡期間,再進(jìn)入到IOT的大數(shù)據(jù)3.0時代,隨之而來的是數(shù)據(jù)架構(gòu)的變化。
2018 年 5 月 18-19 日,由 51CTO 主辦的全球軟件與運(yùn)維技術(shù)峰會在北京召開。在“大數(shù)據(jù)處理技術(shù)”分會場,來自易觀智庫的CTO郭煒先生為我們帶來了《Lambda架構(gòu)已死,新一代的去ELT化IOTA架構(gòu)》的主題演講。
他就Lambda與Kappa架構(gòu)的發(fā)展及優(yōu)缺點展開,分享IOTA大數(shù)據(jù)架構(gòu)的思路及優(yōu)缺點,以及易觀在IOTA架構(gòu)領(lǐng)域的實踐經(jīng)驗。
IOTA架構(gòu)的背景
首先介紹我們遇到過的各種數(shù)據(jù)問題和提出IOTA架構(gòu)的背景。
我們的數(shù)據(jù)來源于手機(jī)的SDK。上圖是易觀當(dāng)前的數(shù)據(jù)規(guī)模。如今月活數(shù)已經(jīng)達(dá)到了5.5個億,其中包含有大概20多億個用戶畫像(Profile),并且已“打上了”各種維度的標(biāo)簽。
那么面對這么多維度的數(shù)據(jù)量,以及層出不窮的新數(shù)據(jù),我們該如何支持好各種數(shù)據(jù)的運(yùn)作呢?
我們先來看看IOTA架構(gòu)的提出背景。上圖右側(cè)是易觀在前兩年構(gòu)建的大數(shù)據(jù)架構(gòu),底層是SDK采集各類數(shù)據(jù)的過程。
由于每天都會有幾百億條的數(shù)據(jù)量,因此我們在SDK上采取的是“云+端”的控制策略,以避免底層SDK淪為導(dǎo)流層。
目前我們使用的接收帶寬已達(dá)到6個GB。當(dāng)有并發(fā)數(shù)據(jù)傳到我們的接收端時,可能會出現(xiàn)幾個GB以上的流量爆增,因此我們要避免這種類似DDoS情況的出現(xiàn)。
在底層上面,我們基于Kafka自行定制了各種內(nèi)部使用的隊列與分發(fā)。與此同時,我們實現(xiàn)了多方的HDFS查詢,并基于此構(gòu)建了批量查詢的Hive。
對于前端的各種產(chǎn)品,我們用Greenplum實現(xiàn)了Ad—hoc查詢。同時,我們用Presto來滿足內(nèi)部分析師的各種查詢需求。
圖中的右側(cè)部分是內(nèi)部的一些數(shù)據(jù)治理服務(wù),包括對源數(shù)據(jù)的管理、數(shù)據(jù)口徑與質(zhì)量的檢測、以及左側(cè)綠色的各種調(diào)度服務(wù)。
上述便是我們在前兩年構(gòu)建的內(nèi)部大數(shù)據(jù)結(jié)構(gòu)。當(dāng)然,我們也遇到了如下各種問題:
- 如今IoT的時代已經(jīng)來臨,各種智能硬件設(shè)備接踵而至,包括智能手環(huán),醫(yī)用糖尿病篩查設(shè)備、智能WiFi、BCON和智能攝像頭等。隨著數(shù)據(jù)越來越復(fù)雜,簡單的移動客戶端已經(jīng)無法滿足我們采集和分析數(shù)據(jù)的需求了。
- 隨著IoT設(shè)備的面市和產(chǎn)生的巨大數(shù)據(jù)量級,其采集頻次遠(yuǎn)大于人工點擊,這給整個架構(gòu)帶來了更大的挑戰(zhàn)。
- 數(shù)據(jù)格式不統(tǒng)一,例如一種云攝像頭的數(shù)據(jù)格式,就不一定與其他廠商的IoT攝像頭相同。
- 數(shù)據(jù)格式多變,會導(dǎo)致業(yè)務(wù)查詢的頻繁變更。我們易觀的70多名分析師,他們所要求的數(shù)據(jù)類型,每天都不盡相同。
- 數(shù)據(jù)需要能夠被實時地查詢到。
我們以轉(zhuǎn)化查詢?yōu)槔耗彻疽陔p十一大促的活動中,查詢一下自己前一個小時廣告投放的效果、以及價格波動對于用戶***購買的影響。這些都屬于Ad-hoc式查詢。
Lambda架構(gòu)
我們回頭來看Lambda架構(gòu)。如今80%~90%的企業(yè)都在使用Lambda架構(gòu)進(jìn)行自己的大數(shù)據(jù)分析,包括我們自己也是從Lambda架構(gòu)過渡而來。
如圖所示,所有的數(shù)據(jù)采集都是從最左側(cè)進(jìn)入架構(gòu)的。根據(jù)不同的SDK,各種數(shù)據(jù)源所采集到的數(shù)據(jù)格式會有所不同。它們在此匯聚到我們云端的大數(shù)據(jù)平臺。
我們通過兩條線來保證數(shù)據(jù)的實時性和有效性:
- 通過傳統(tǒng)的ETL,我們將數(shù)據(jù)做成批量任務(wù)—Batch Data,每晚運(yùn)行一次,次日早上我們?nèi)ゲ榭聪嚓P(guān)的數(shù)據(jù)結(jié)果。
- 為了保證實時地采集,例如:需要根據(jù)銷售量來做出智能推薦的決策,或是查看當(dāng)日的PV/UV,那么我們就去“跑”一些Data Streaming(數(shù)據(jù)流)。
上述兩條線的結(jié)果,最終都被放入一個Result Database(結(jié)果數(shù)據(jù)庫,如某個MySQL)中,以方便我們的前端應(yīng)用,通過該數(shù)據(jù)庫,來查詢后端的數(shù)據(jù)。
但是,該架構(gòu)存在著如下問題:
1. 業(yè)務(wù)方會發(fā)現(xiàn),次日看到的數(shù)據(jù)比昨晚看到的要少。原因在于:數(shù)據(jù)在被放入Result Database時,走了兩條線的計算方式:一條線是ETL按照某個口徑“跑”過來,得到更為準(zhǔn)確的批量處理結(jié)果;另一條線是通過Streaming“跑”過來,依靠Hadoop Hive或其他算法得出的實時性結(jié)果。當(dāng)然它犧牲了部分的準(zhǔn)確性。可見,這兩個來自批量的和實時的數(shù)據(jù)結(jié)果是對不上的,因此大家覺得很困惑。
2. 針對每一次實時分析的需求,都需要用Data Streaming重新開發(fā)一次。無論您是用Storm、Spark Streaming還是Flink,只要你想查看某個結(jié)果,就必須開發(fā)一次流式計算。也就是說,我們要按需做各種各樣的ETL開發(fā),這顯然效率不高。
3. 我們做數(shù)據(jù)清洗的目的就是為了得到更好的數(shù)據(jù)格式,然后放到大數(shù)據(jù)平臺之上。但是由于平臺需要通過處理,來適配不同的采集格式,因此,我們無法迅速地呈現(xiàn)不同領(lǐng)域的實時數(shù)據(jù)。
KAPPA架構(gòu)
后來LinkedIn提出了一個新的架構(gòu):KAPPA。它的理念是:鑒于大家認(rèn)為批量數(shù)據(jù)和實時數(shù)據(jù)對不上是個問題,它直接去掉了批量數(shù)據(jù);而直接通過隊列,放入實時數(shù)據(jù)之中。
例如:將所有的數(shù)據(jù)直接放到原來的Kafka中,然后通過Kafka的Streaming,去直接面向***的查詢結(jié)果。
當(dāng)然,該架構(gòu)也存在著一些問題:
1. 不能及時查詢和訓(xùn)練。例如:我們的分析師想通過一條SQL語句,來查詢前五秒的狀態(tài)數(shù)據(jù)。這對于KAPPA架構(gòu)是很難去實現(xiàn)的。
2. 面對各種需求,它同樣也逃不過每次需要重新做一次Data Streaming。也就是說,它無法實現(xiàn)Ad—hoc查詢,我們必需針對某個需求事先準(zhǔn)備好,才能進(jìn)行數(shù)據(jù)分析。
3. 新數(shù)據(jù)源的結(jié)構(gòu)問題。例如:要新增一臺智能硬件設(shè)備,我們就要重新開發(fā)一遍它對應(yīng)的適配格式、負(fù)責(zé)采集的SDK、以及SDK的接收端等,即整體都要重復(fù)開發(fā)一遍。
因此,雖然KAPPA架構(gòu)比Lambda好的方面是不必實時地把ETL數(shù)據(jù)做兩遍,但是它仍然存在著結(jié)構(gòu)上的問題。
IOTA架構(gòu)
至此,我們提出了IOTA架構(gòu)。在取名上,它是基于希臘字母的順序,即:從IOTA、到KAPPA、再到Lambda的。
我們首先來看看IOTA架構(gòu)的基本思路。鑒于大家既需要支持實時數(shù)據(jù)、又要支持Ad—hoc查詢,還要支持各種數(shù)據(jù)的適配,因此該架構(gòu)必然會有一些“約束”。
***個約束:我們應(yīng)事先確定好通用的數(shù)據(jù)模型(Common Data Model)。例如:我們在做用戶行為分析時,可以通過一種“主-謂-賓”的模型去描述:“誰對什么做了什么”。而剩下的其他修飾詞,則完全可以被作為其他的列和參數(shù)。
在此模型基礎(chǔ)上,所有的數(shù)據(jù)其實并非在中央被處理,而是在最開始的SDK端被操作。在此我們可以引入邊緣計算的概念,即:不是在云端加工數(shù)據(jù),而是把所有數(shù)據(jù)分散到從數(shù)據(jù)產(chǎn)生到***存儲整個過程之中。
另外,由于一般公司的業(yè)務(wù)并不會天天發(fā)生變化,因此我們可以抽象出一套完整的業(yè)務(wù)模型,進(jìn)而實現(xiàn)在邊緣端做數(shù)據(jù)統(tǒng)一,而不是在云端進(jìn)行。
如上圖中所提到的Common Data Model的示例。我們可以用“主-謂-賓”模型,即“X用戶 – 事件1 – A頁面(2018/4/11 20:00)”來進(jìn)行抽象。
當(dāng)然,我們也可以根據(jù)業(yè)務(wù)的不同需求,使用“產(chǎn)品-事件”、或“地點-時間”模型。
第二個約束:對于同樣的硬件設(shè)備而言,我們完全可以將“X用戶的MAC 地址-出現(xiàn)- A樓層(2018/4/11 18:00)”模型,與前面提到的“主-謂-賓”模型統(tǒng)一成一種。
也就是說,無論是App小程序、Web頁面、攝像頭、還是IoT智能WiFi,只要數(shù)據(jù)模型是統(tǒng)一的,你就能夠在數(shù)據(jù)產(chǎn)生端,統(tǒng)一整體的數(shù)據(jù)格式。
第三個約束:由于云端的數(shù)據(jù)只負(fù)責(zé)存儲和查詢,而不再負(fù)責(zé)做加工。
因此在IOTA架構(gòu)中,有著如下主要的組成部分:
- Real Time Data Cache,對于海量的實時數(shù)據(jù),我們會存儲到云端,但是在將它們直接導(dǎo)入數(shù)據(jù)庫的時候則會產(chǎn)生延遲,因此我們需要選用Hbase或Kudu之類的組件,來實現(xiàn)簡單的列式存儲。
- Historical Data,針對的是大量歷史數(shù)據(jù)的底層存儲,我們可以在云端用到HDFS。而之所以不將實時數(shù)據(jù)直接接入HDFS,是為了避免產(chǎn)生大量的碎片文件,而影響到最終的查詢效率。
- Dumper,該程序?qū)崿F(xiàn)并銜接了從Real Time Data Cache到數(shù)據(jù)的存儲。我們可以按照既定的規(guī)則(每五分鐘、或到達(dá)一百萬條數(shù)據(jù)時),將Real Time Data Cache“落”到HDFS文件中。同時,我們也可以添加相關(guān)的索引,為后面的Query Engine做好準(zhǔn)備。
- Query Engine,它可以用到的計算引擎包括:Spark、Presto、Impala等。通過Query Engine,我們既可以查詢存儲在HDFS的底層數(shù)據(jù),又可以查詢幾分鐘前的實時數(shù)據(jù)。另外,通過兩者的合并,分析師還能夠?qū)崿F(xiàn)智能分析。
因此,基本的流程是:底層的SDK先將數(shù)據(jù)的格式予以統(tǒng)一,接著先存放在Cache里,然后再放入Historical Data中。
而在查詢時,我們可以暴露一個SQL接口(如:Presto或SparkSQL),以供分析師們直接查看到幾秒之前的各種數(shù)據(jù)狀態(tài)。
例如:我們可以通過Query Engine查詢到:用戶是如何從登錄頁面最終點擊到了購買頁面,他們所經(jīng)歷的智能路徑和觸發(fā)過的事件等。這些一連串的前后相關(guān)的數(shù)據(jù)都能夠被實時地顯示出來,甚至包括一些Ad-hoc的查詢。
總結(jié)
我們再回顧一下上面提到的重要方面:
- 通用數(shù)據(jù)模型非常重要,它貫穿整個業(yè)務(wù)的始終,從SDK的產(chǎn)生直至***的存儲,以及按需查詢。當(dāng)然,如果模型本身上無法固定,我們則可以用Protobuf在SDK中先行定義一個模型。在做好了協(xié)議架構(gòu)的基礎(chǔ)上,如果后期需求固定下來了,我們只要保持從底層到上層的模型統(tǒng)一,那么修改起來就十分方便,甚至都不會涉及到云端存儲的改動。
- 數(shù)據(jù)緩沖區(qū),主要用來減少索引的延遲和歷史數(shù)據(jù)的碎片等問題。
- 歷史數(shù)據(jù)沉浸區(qū),主要是為了Ad-hoc查詢,其包括建立好各種相關(guān)的索引,以實現(xiàn)秒級的結(jié)果返回。
- SDK,過去我們只是讓SDK進(jìn)行簡單地埋點和采集,而如今,我們在SDK上增加了一些簡單的計算,讓數(shù)據(jù)在產(chǎn)生端就完成了轉(zhuǎn)化。
- 如果產(chǎn)生端(如攝像頭)的性能不夠,我們可以為它添加一臺專門用作轉(zhuǎn)化的EdgeAIServer服務(wù)器,從而實現(xiàn)上述提到的“主-謂-賓”模型的格式輸出。當(dāng)然,對于App和H5頁面來說,由于沒有計算的工作量,因此只要求埋點格式即可。
根據(jù)上述對于IOTA模型的介紹,我們對原來的大數(shù)據(jù)系統(tǒng)做了相應(yīng)的調(diào)整。
具體情況如下:
- 我們的數(shù)據(jù)查詢已不再需要ETL,而是通過Query Engine實現(xiàn)了數(shù)據(jù)的各種留存、轉(zhuǎn)化、營銷和分析等操作。
- 針對查詢服務(wù),我們基于Presto進(jìn)行了二次開發(fā),并構(gòu)建出了“秒算平臺”。
- 對應(yīng)上面提到過的“主-謂-賓”模型,我們相應(yīng)地制定了兩個主要的數(shù)據(jù)存儲結(jié)構(gòu):“用戶/事件”,即:“誰在哪發(fā)生了什么”。
- 為了保證緩存中的數(shù)據(jù)能夠被順利地“灌”入Historical Data所對應(yīng)的存儲區(qū)域,我們配置了DumpMR服務(wù)模塊。
- 針對“灌入”的數(shù)據(jù)會被分成很多個文件,如:每十分鐘產(chǎn)生一個文件的情況,我們配置了MergerMR服務(wù)模塊,它能夠?qū)⑦@些碎片化的多個文件合并成為一個大的存儲塊。另外,我們還為這些數(shù)據(jù)重新添加了索引,以方便實時地進(jìn)行計算。
- 在“秒算平臺”上,我們運(yùn)用Hbase來對實時數(shù)據(jù)進(jìn)行緩存,并用HDFS來對歷史數(shù)據(jù)進(jìn)行存儲。
- 由于我們將Presto作為查詢服務(wù)引擎,為了能讓它能夠連接HDFS和Hbase,我們自行研發(fā)了一些Connector。通過我們的二次開發(fā),它能夠支持諸如MySQL、Redis和MongoDB等各種第三方數(shù)據(jù)庫的查詢。
- 我們對從用戶處收集來的大數(shù)據(jù),根據(jù)上面提到的“用戶/事件”和“主-謂-賓”模型,直接放到SDK里,進(jìn)行相關(guān)的計算。
眾所周知,任何一種軟件只有經(jīng)歷了開放源代碼,才能夠不斷地促進(jìn)自己的完善與發(fā)展。雖然我們的系統(tǒng)目前尚屬內(nèi)部版本,但是我們計劃在今年底,將上述提到的基于IOTA架構(gòu)模型的“秒算平臺”開源出來,以供大家使用。
有了這樣的平臺,大家可以基于其存儲引擎來快速地進(jìn)行二次開發(fā),而不必自己去寫HDFS、Connector、DumpMR、MergerMR、以及一大堆Profile相關(guān)的代碼。我們會把這些“坑”事先幫大家“填好”,大家直接用它去做用戶級別的數(shù)據(jù)分析便可。
目前,就易觀大數(shù)據(jù)混合云的數(shù)據(jù)規(guī)模和性能而言,已經(jīng)能夠根據(jù)我們分析師的各種Ad-hoc數(shù)據(jù)查詢需求,實現(xiàn)了秒級的結(jié)果返回。同時,我們內(nèi)部的秒算服務(wù)引擎,也能夠支持并提供帶有各種分析結(jié)果的分析報告。
郭煒,現(xiàn)任易觀CTO,負(fù)責(zé)易觀整體技術(shù)架構(gòu)及分析產(chǎn)品線。北大計算系本科與研究生,在Teradata,IBM,中金負(fù)責(zé)大數(shù)據(jù)方向架構(gòu)師或研發(fā)總監(jiān),后任萬達(dá)電商數(shù)據(jù)部總經(jīng)理,聯(lián)想研究院大數(shù)據(jù)總監(jiān)。在電商、移動互聯(lián)網(wǎng)、商業(yè)地產(chǎn)、百貨、移動通信、零售、院線等多個業(yè)務(wù)領(lǐng)域大數(shù)據(jù)方面具有搭建團(tuán)隊、系統(tǒng)以及分領(lǐng)域的分析與算法經(jīng)驗。
【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】