數(shù)據(jù)編排技術(shù)在聯(lián)通的應(yīng)用
首先,做一下自我介紹。我是聯(lián)通軟件研究院大數(shù)據(jù)工程師張策,同時(shí)在Alluxio社區(qū)擔(dān)任PMC member,也是Presto Contributor,對(duì)開(kāi)源大數(shù)據(jù)比較感興趣,希望平時(shí)與大家多多交流。
全文將圍繞以下內(nèi)容展開(kāi):
- 使用場(chǎng)景
- 在緩存加速方面的應(yīng)用
- 在存算分離方面的應(yīng)用
- 在混合負(fù)載領(lǐng)域的應(yīng)用
- 輕量級(jí)分析相關(guān)探索
01 使用場(chǎng)景
首先介紹Alluxio作為分布式緩存加速大數(shù)據(jù)計(jì)算的使用場(chǎng)景。我們事業(yè)部存在多個(gè)數(shù)據(jù)處理與數(shù)據(jù)分析業(yè)務(wù),這些業(yè)務(wù)分布在不同的平臺(tái)。使用GreenPlum數(shù)據(jù)庫(kù)的數(shù)據(jù)處理業(yè)務(wù)基于批處理存儲(chǔ)過(guò)程完成數(shù)據(jù)加工,對(duì)計(jì)算時(shí)間有嚴(yán)格的要求,有明確的deadline。這些業(yè)務(wù)遇到的主要問(wèn)題是GreenPlum集群規(guī)模達(dá)到幾十臺(tái)時(shí)遇到擴(kuò)容瓶頸,進(jìn)一步擴(kuò)展對(duì)業(yè)務(wù)運(yùn)維工程師帶來(lái)很大挑戰(zhàn);還有一部分業(yè)務(wù)基于hive運(yùn)行T+1批處理作業(yè),遇到的主要問(wèn)題是內(nèi)存、CPU等資源消耗比較大,并行度不高,跑的速度比較慢;還有一些傳統(tǒng)統(tǒng)計(jì)業(yè)務(wù)是跑在Oracle上,Oracle單機(jī)跑的效果不是特別好,并且Oracle比較貴,一臺(tái)小型機(jī)可能就要兩千多萬(wàn),業(yè)務(wù)方期望能有其他數(shù)據(jù)分析平臺(tái)替代Oracle。
當(dāng)時(shí),我們的課題是是基于Spark、Hadoop這個(gè)開(kāi)源體系,去做一個(gè)統(tǒng)一的計(jì)算平臺(tái),把上述三個(gè)引擎承接的業(yè)務(wù)全部接過(guò)來(lái)。我們直接用Spark + HDFS遇到了一些問(wèn)題:
首先它的性能是沒(méi)有辦法滿足GreenPlum承載的生產(chǎn)業(yè)務(wù),因?yàn)镚reenPlum是MPP數(shù)據(jù)庫(kù),同等體量下它會(huì)比Spark要快很多;其次GreenPlum承載的業(yè)務(wù)中存在伴生的交互式查詢的場(chǎng)景,同樣性能也是沒(méi)有辦法去滿足的。接著,對(duì)于一些批處理的業(yè)務(wù)來(lái)說(shuō),Spark + HDFS比較欠缺穩(wěn)定性,批處理的業(yè)務(wù)每一次任務(wù)周期會(huì)有幾千、幾萬(wàn)個(gè)SQL去做迭代計(jì)算,任務(wù)如果經(jīng)常失敗的話,沒(méi)有辦法很好地在那之前保證去完成。
所以,為了加速Spark計(jì)算,我們引入了Alluxio來(lái)加速數(shù)據(jù)的讀寫(xiě)性能,提高數(shù)據(jù)寫(xiě)入的穩(wěn)定性,以及接管Spark Cache后提升Spark作業(yè)的穩(wěn)定性。這是我們一開(kāi)始采用的架構(gòu),數(shù)據(jù)編排在我們的整個(gè)架構(gòu)中的定位是緩存加速層。
02 在緩存加速方面的應(yīng)用
具體看一下使用案例,如果拿加速迭代計(jì)算來(lái)說(shuō),我們會(huì)把Sink直接寫(xiě)到Alluxio上,然后下一個(gè)SQL的Source去讀這個(gè)Sink,把Source和Sink之間的串聯(lián)交給Alluxio的緩存去做,這樣可以比較顯著提升整個(gè)pipeline的穩(wěn)定性。因?yàn)椴恍枰俸痛疟P(pán)交互,可以極大降低磁盤(pán)壓力。而通過(guò)內(nèi)存,pipeline的穩(wěn)定性得到了比較好的改善,通過(guò)直接讀取內(nèi)存會(huì)提高整個(gè)pipeline的運(yùn)行速度。
第二個(gè)使用案例,是我們通過(guò)Alluxio去共享整個(gè)Job之間的數(shù)據(jù),而避免使用Spark Cache。通過(guò)Spark Cache方式對(duì)會(huì)對(duì)整個(gè)Executor JVM造成比較大的壓力。性能測(cè)試結(jié)果表明在數(shù)據(jù)量達(dá)到一定規(guī)模的情況下,Spark Cache的性能是要比Alluxio差一些。而且Alluxio隨著Spark中間數(shù)據(jù)的增大,它對(duì)性能的影響是可以預(yù)測(cè)的,是線性而不是指數(shù)性上漲的。所以說(shuō),我們選擇用Alluxio做中間數(shù)據(jù)的共享層。
為了增些數(shù)據(jù)讀取的性能,可以顯示的為每個(gè)路徑去配置副本浮動(dòng)范圍。而且Alluxio還支持了數(shù)據(jù)預(yù)加載的功能--distributedLoad.這個(gè)在2021年的時(shí)候,社區(qū)也是花了很多的精力在上面,目前是做的十分完善的工具了。我們可以在執(zhí)行一些固定任務(wù)之前,提前先把數(shù)據(jù)加載到內(nèi)存。這樣可以提高整個(gè)pipeline的運(yùn)行速度。此外,Alluxio還支持一些內(nèi)存操作工具,比如pin和free,這樣的話能方便我們更好地去管理內(nèi)存。就是按照我們既定的一個(gè)pipeline可以把整個(gè)內(nèi)存布局得到最好的優(yōu)化。
03 在存算分離方面的應(yīng)用
接下來(lái)是跟Alluxio數(shù)據(jù)編排Policy有關(guān)的例子。比如我們一個(gè)Spark任務(wù)去讀一個(gè)數(shù)據(jù),它可能會(huì)在每個(gè)worker上都拉起一些副本,比如重復(fù)使用的一些數(shù)據(jù)。這種情況可能會(huì)迅速把緩存占滿。對(duì)于這種情況,Alluxio可以提供一個(gè)叫確定性哈希的策略。這個(gè)策略可以使我們?cè)诠潭ǖ哪硯讉€(gè)worker上去讀。這樣可以把整個(gè)集群的副本數(shù)加起來(lái),能更有效地去使用空間。除此之外,針對(duì)大量場(chǎng)景,它還支持一些跟負(fù)載均衡相關(guān)的策略。比如最高可控策略,它會(huì)選擇整個(gè)集群內(nèi)空間剩余量最大的一個(gè)worker去讀。這樣可以使所有worker的使用比較均衡。但是,它也有一些問(wèn)題,當(dāng)大量Alluxio Client 在Spark Executor這邊如果大量去擠兌一個(gè)Alluxio Worker的話,那么可能會(huì)導(dǎo)致這個(gè)worker的使用量瞬間打滿,出現(xiàn)性能降級(jí)的情況。針對(duì)這種情況,我們可以去選擇一個(gè)輪循策略,在若干有剩余量的work之間去輪循使用,這樣可以比較好地去實(shí)現(xiàn)集群的負(fù)載均衡。
從總的使用效果來(lái)看,Alluxio還帶來(lái)了比較大的性能與穩(wěn)定性的提升。這里是一個(gè)比較典型的Spark Task統(tǒng)計(jì),Alluxio對(duì)整個(gè)GC的時(shí)間優(yōu)化,還有整個(gè)任務(wù)總耗時(shí)的優(yōu)化的收益是比較顯著的。它最大的優(yōu)點(diǎn)是可以顯著降低每批次Job的重算概率,從而使整個(gè)過(guò)程更加穩(wěn)定,更加可預(yù)測(cè)。
最終效果是我們從之前GreenPlum遷移過(guò)來(lái)的核心業(yè)務(wù)的規(guī)模已經(jīng)有接近70倍的增長(zhǎng),并且承接的用戶數(shù)相比之前提高了100%,業(yè)務(wù)總體提速了26個(gè)小時(shí)。交互式查詢業(yè)務(wù)目前日常數(shù)據(jù)已經(jīng)達(dá)到60TB,如使用Spark單表2.5tb數(shù)據(jù),查詢耗時(shí)也是分鐘級(jí)別。原先Oracle業(yè)務(wù)遷移到Spark后可以做用戶級(jí)的計(jì)算,這對(duì)于他們來(lái)講是具有很大的價(jià)值。
接下來(lái)是我們針對(duì)集群繼續(xù)發(fā)展的特點(diǎn),做了在存算分離方面的一些建設(shè)。存算分離的背景大概是什么樣的?這主要是跟整個(gè)集群的發(fā)展有一定的關(guān)系。首先在我們這邊的平臺(tái)建設(shè)是跟著業(yè)務(wù)走。隨著業(yè)務(wù)快速增長(zhǎng),會(huì)出現(xiàn)資源碎片化的情況。如圖所示,第一年新建一個(gè)機(jī)房,我們占用了一部分機(jī)架,其他業(yè)務(wù)或部門(mén)也會(huì)占用一些機(jī)架。到第二年的時(shí)候,第一年的機(jī)房就滿了,第二年新建的機(jī)房大家可以各自去申請(qǐng)一些。這就導(dǎo)致整個(gè)機(jī)器不具有連續(xù)性,可能會(huì)跨機(jī)房,甚至可能會(huì)跨樓,有時(shí)候甚至還會(huì)跨數(shù)據(jù)中心。與之伴隨的就是業(yè)務(wù)快速增長(zhǎng),基本上處于逐年倍增的情況,而且資源申請(qǐng)周期非常長(zhǎng),至少需要一年的時(shí)間才能交付,最后導(dǎo)致的情況就是集群呈現(xiàn)碎片化。
更為糟糕的是在業(yè)務(wù)增長(zhǎng)過(guò)程中,其實(shí)它的資源需求是不平衡的,主要是存儲(chǔ)與計(jì)算之間的不平衡。首先,一個(gè)客觀事實(shí)是歷史數(shù)據(jù)的存儲(chǔ)需求是逐年遞增的。之前業(yè)務(wù)只需要保留1至2個(gè)月的數(shù)據(jù)。但是現(xiàn)在因?yàn)橐恍v史的趨勢(shì)分析或是各方面測(cè)算,一些主要業(yè)務(wù)的數(shù)據(jù)需要保存12至24個(gè)月。業(yè)務(wù)數(shù)據(jù)每個(gè)周期之間的環(huán)比漲幅大概是10%,漲幅大時(shí)甚至有5~10倍的情況,主要是跟業(yè)務(wù)邏輯變化相關(guān)。其次,存儲(chǔ)規(guī)模的漲幅大概是計(jì)算規(guī)模漲幅的5到6倍,這也是存儲(chǔ)計(jì)算發(fā)展不平衡的情況。
我們使用了存算分離的技術(shù)來(lái)解決這些問(wèn)題。
首先解決計(jì)算資源的問(wèn)題。我們向其他的業(yè)務(wù)租借了一個(gè)現(xiàn)有的集群,利用該集群空閑的夜間完成數(shù)據(jù)加工作業(yè)。我們?cè)谏厦娌渴鹆艘惶譙park,以及Alluxio和我們集群的HDFS構(gòu)成一套存算分離的數(shù)據(jù)分析系統(tǒng)。為什么不在該集群部署Hadoop?原因是租借的業(yè)務(wù)集群已經(jīng)搭建了一套Hadoop,我們不被允許二次搭建Hadoop,也不允許去使用他們的Hadoop。所以,我們就用該業(yè)務(wù)集群的Alluxio去掛載我們平臺(tái)的HDFS。掛載HDFS之后就跟我們自己平臺(tái)保持一樣的命名空間,這樣看起來(lái)都是一樣的,基本上做到用戶無(wú)感知。
更詳細(xì)的如此圖所示,就是對(duì)于2個(gè)Alluxio來(lái)說(shuō),看到的Path都是一樣的,都是映射到HDFS的一個(gè)Path,所以用戶認(rèn)為這兩個(gè)Path都是一樣的。我們?cè)谧x寫(xiě)不同Path的時(shí)候,會(huì)讓不同的Alluxio分別執(zhí)行讀寫(xiě)操作。比如遠(yuǎn)程Alluxio對(duì)Path1是只讀的,它會(huì)去寫(xiě)Path2,本地Alluxio會(huì)寫(xiě)Path1,但只會(huì)去讀Path2,這樣就避免了兩個(gè)Alluxio相互之間沖突。
在具體落實(shí)方案上,我們還使用了一些自己的設(shè)計(jì),來(lái)避免存算分離會(huì)遇到的一些問(wèn)題。
首先,我們?cè)谶h(yuǎn)程業(yè)務(wù)集群這塊,是基于RocksDB+Raft HA 的方式來(lái)解決沒(méi)有本地HDFS時(shí)Alluxio HA元數(shù)據(jù)操作性能的問(wèn)題。因?yàn)槲覀兊腍DFS在我們的集群,中間有一定的網(wǎng)絡(luò)消耗。如果我們直接還是采用原來(lái)的zookeeper ha,首先我們需要在他們的集群搭打一套zookeeper ha,以及把元數(shù)據(jù)放在我們自己集群的HDFS上,跨網(wǎng)絡(luò)元數(shù)據(jù)交互可能會(huì)帶來(lái)很多的不確定性。比如帶寬打滿了,或者是因?yàn)槠渌W(wǎng)絡(luò)波動(dòng)的因素,會(huì)導(dǎo)致Alluxio本身的性能抖動(dòng),甚至可能出現(xiàn)因?yàn)閿?shù)據(jù)寫(xiě)入或者讀取超時(shí)導(dǎo)致整個(gè)Alluxio掛掉的情況。所以,我們選擇了Alluxio 2.x之后不斷去建設(shè)去完善的RocksDB+Raft HA的方式來(lái)解決這個(gè)問(wèn)題。
其次,我們?cè)跇I(yè)務(wù)集群這邊因?yàn)橐獫M足所有中間數(shù)據(jù)的存儲(chǔ),提升整個(gè)計(jì)算性能,所以我們使用HDD作為存儲(chǔ)介質(zhì)。Spark作業(yè)的中間過(guò)程數(shù)據(jù)直接存儲(chǔ)在緩存磁盤(pán)里,不會(huì)與UFS有任何交互,所以對(duì)于用戶來(lái)說(shuō),這種模式的性能是不受影響的。
第三,最終結(jié)果還可以持久化至集群。因?yàn)樽罱K結(jié)果的數(shù)量也不是特別大,所以它的耗時(shí)還是可以接受的。最后對(duì)于用戶來(lái)說(shuō),他可能需要跨集群部署任務(wù),我們是在租借的業(yè)務(wù)集群之內(nèi)搭建了一個(gè)Dolphin Scheduler Worker,通過(guò)Dolphin的調(diào)度策略,幫助用戶把他的特定任務(wù)起在這個(gè)Worker上面。通過(guò)Worker的選擇來(lái)控制它提交到不同的集群。對(duì)于用戶來(lái)說(shuō)只是配置上做了變更,作業(yè)提交入口以及管理入口都是相同的,解決了跨集群作業(yè)管理的問(wèn)題。
實(shí)現(xiàn)計(jì)算混合部署之后,我們又接到了大量的數(shù)據(jù)存儲(chǔ)需求。但是我們的集群短時(shí)間內(nèi)沒(méi)有辦法擴(kuò)容了,所以我們申請(qǐng)了一批大容量存儲(chǔ),然后把大容量存儲(chǔ)mount到Alluxio,將歷史數(shù)據(jù)自動(dòng)化降級(jí)到大容量存儲(chǔ)上,查詢的時(shí)候就經(jīng)由Alluxio透明訪問(wèn)。我們會(huì)把前2個(gè)月至前12個(gè)月的歷史數(shù)據(jù)降級(jí)到大容量存儲(chǔ)上,本地集群只保留最近幾個(gè)月會(huì)頻繁參與計(jì)算的數(shù)據(jù)。對(duì)于用戶來(lái)說(shuō),訪問(wèn)的路徑跟之前還是一樣的,我們通過(guò)mount方式屏蔽了歷史數(shù)據(jù)分層管理的差異性。對(duì)于我們的好處是單位服務(wù)器的存儲(chǔ)容量顯著提高了,大容量存儲(chǔ)可以獨(dú)立擴(kuò)容,對(duì)于我們來(lái)說(shuō)緩解了很大的存儲(chǔ)壓力。
以下是我們做完存算分離以后的實(shí)際效果。
首先,某核心用戶租借算力占平臺(tái)分配算力的82%,這個(gè)是比較大的提升。承接新業(yè)務(wù)使用租借算力占比達(dá)到50%,Alluxio管理ETL過(guò)程數(shù)據(jù)達(dá)到148TB,算是非常龐大的數(shù)字了。因?yàn)锳lluxio其實(shí)作為緩存來(lái)講并不會(huì)去管理特別大量的數(shù)據(jù)。管理100至200TB這個(gè)數(shù)據(jù)量,我們跟社區(qū)一起做了很多工作,包括worker啟動(dòng)超時(shí)等優(yōu)化,以滿足中間數(shù)據(jù)存儲(chǔ)的需求。單獨(dú)擴(kuò)容的大容量存儲(chǔ)給我們帶來(lái)的好處是單臺(tái)服務(wù)器的存儲(chǔ)容量提升5倍,計(jì)算集群采用的計(jì)算型服務(wù)器存儲(chǔ)容量比較小,大容量存儲(chǔ)單臺(tái)機(jī)器就能存儲(chǔ)90TB數(shù)據(jù),服務(wù)器臺(tái)數(shù)相同的情況下,容量提升比較明顯,所以歷史數(shù)據(jù)存儲(chǔ)顯著降低,擴(kuò)容成本是降低了83%。
04 在混合負(fù)載領(lǐng)域的應(yīng)用
當(dāng)集群向后繼續(xù)發(fā)展的時(shí)候,我們引入了更多的計(jì)算引擎來(lái)適配更多的業(yè)務(wù)場(chǎng)景以得到更好的效果。其中比較典型的場(chǎng)景是我們?cè)谝粋€(gè)平臺(tái)上同時(shí)提供Spark和Presto,Spark主要用于ETL,Presto提供即席查詢服務(wù)。它們共用Alluxio時(shí)會(huì)遇到一些問(wèn)題:首先,Alluxio System Cache不支持Quota,沒(méi)有辦法隔離Spark跟Presto之間的用量,由于Spark ETL作業(yè)寫(xiě)入的數(shù)據(jù)較大,數(shù)據(jù)直接寫(xiě)入Alluxio作為pipeline下一個(gè)節(jié)點(diǎn)的讀取加速。這種情況下內(nèi)存沖刷比較頻繁,會(huì)一次性占用較多的內(nèi)存。這樣Presto剛完成數(shù)據(jù)加載,想查數(shù)據(jù)的時(shí)候發(fā)現(xiàn)緩存中沒(méi)有了,Presto查詢的緩存利用率不是特別高。
第二個(gè)情況是一些用戶使用TensorFlow做自然語(yǔ)言處理或者時(shí)間序列分析的AI計(jì)算。在AI計(jì)算之前,用戶首先基于Spark做分布式ETL,然后想把ETL結(jié)果直接拿給TensorFlow使用,在這種情況下,用戶很難把分布式的數(shù)據(jù)和本地?cái)?shù)據(jù)聯(lián)系到一起。第三方框架比如TensorFlow on Spark一般都會(huì)封裝一些標(biāo)準(zhǔn)模型。用戶使用的模型不是主流模型,但實(shí)際效果較好,這種情況沒(méi)有辦法套用現(xiàn)用的第三方框架,直接將Spark DataFrame轉(zhuǎn)換成TensorFlow的數(shù)據(jù)模型直接使用。這樣TensorFlow還是一種讀取本地文件的模式,就是不是很好的能把Spark與TensorFlow聯(lián)動(dòng)起來(lái)。
針對(duì)使用案例剛才講到的一些問(wèn)題,我們做了一些改進(jìn)。首先,Presto這邊我們放棄了使用Alluxio System Cache,而是使用Alluxio Local Cache緩存數(shù)據(jù),這樣跟Spark使用的Alluxio System Cache進(jìn)行隔離。我們會(huì)為每個(gè)Presto Worker去開(kāi)辟一個(gè)獨(dú)立的緩存。這個(gè)緩存是放在Ramdisk上面,官方推薦放到SSD里邊也是可以的。緩存不占用Presto Worker的JVM空間,不會(huì)對(duì)GC造成額外負(fù)擔(dān)。除此之外,因?yàn)槲覀冇幸恍┐疟P(pán)場(chǎng)景,所以跟社區(qū)一起完善了基于RockDB的緩存實(shí)現(xiàn)。以上是我們?cè)诰彺娓綦x上做的一些設(shè)計(jì)。
在AI這邊,我們利用Alluxio Fuse打通了ETL與AI訓(xùn)練和推理。Alluxio Fuse首先做了本地文件跟分布式系統(tǒng)掛載,這樣就可以把分布式文件映射到本地文件。然后用戶可以直接使用讀寫(xiě)本地文件的方式操作一個(gè)分布式系統(tǒng)中的文件,與筆記本上開(kāi)發(fā)的讀寫(xiě)本地代碼的邏輯完全相同。這樣就成功地打通了Spark ETL跟TensorFlow的計(jì)算。Alluxio目前是提供兩種Fuse掛在模式,首先提供為每個(gè)Worker創(chuàng)建一個(gè)Fuse的掛載目錄。這種方式可以更好地提高數(shù)據(jù)訪問(wèn)性能,我們目前使用的是這種模式。還有一種是單獨(dú)起一個(gè)Fuse進(jìn)程,這樣就不需要在本地區(qū)部署Alluxio集群,這種方式有助于靈活部署。大家可以按照自己需要去選擇不同的部署模式。
目前使用的效果,Presto因?yàn)橐肓薈ache,查詢性能提升了50%左右,相比OS Cache更加穩(wěn)定。如果我們都用OS Cache性能是最快的,但因?yàn)榧褐蔚氖菙?shù)據(jù)密集型的負(fù)載,所以O(shè)S Cache不是特別穩(wěn)定,容易被刷下去。相比沒(méi)有Cache加速時(shí),它的查詢性能有不錯(cuò)的提升。大數(shù)據(jù)AI集成方面,用戶可以用TensorFlow去訓(xùn)練推理的代碼不需要做任何改動(dòng),就可以跟Spark ETL做集成,目前首批業(yè)務(wù)是完成了60萬(wàn)用戶的接入,整個(gè)過(guò)程基于Dolphin Scheduler實(shí)現(xiàn)大數(shù)據(jù)+AI全流程自動(dòng)化調(diào)度,用戶的運(yùn)維復(fù)雜度非常低。這里幫Alluxio的邱璐做個(gè)廣告,她目前是Alluxio Fuse的負(fù)責(zé)人。Alluxio Fuse已經(jīng)在微軟、Boss直聘、嗶哩嗶哩、陌陌等公司的生產(chǎn)訓(xùn)練中完成了部署。
05 輕量級(jí)分析相關(guān)探索
現(xiàn)狀一,目前聯(lián)通在大力推動(dòng)數(shù)字化轉(zhuǎn)型,之前很多跟數(shù)據(jù)分析沒(méi)有關(guān)系的業(yè)務(wù),如一些傳統(tǒng)業(yè)務(wù),也想做數(shù)據(jù)分析。利用之前沉淀的數(shù)據(jù),想做預(yù)測(cè)或者是原因定位。目標(biāo)用戶更多是業(yè)務(wù)工程師,更喜歡關(guān)系型數(shù)據(jù)庫(kù)以及SQL。
現(xiàn)狀二,不同的業(yè)務(wù)之間同時(shí)需要訪問(wèn)平臺(tái)運(yùn)營(yíng)的公有數(shù)據(jù),以及訪問(wèn)、管理業(yè)務(wù)私有數(shù)據(jù)。這些私有數(shù)據(jù)的業(yè)務(wù)口徑由業(yè)務(wù)方制定,并按照自己的開(kāi)放策略向其他業(yè)務(wù)方提供。因此共享私有數(shù)據(jù)需要數(shù)據(jù)提供方授權(quán),公有數(shù)據(jù)只需要平臺(tái)授權(quán)就可以。
現(xiàn)狀三,服務(wù)器資源增量目前低于業(yè)務(wù)的需求量,因?yàn)閿?shù)據(jù)分析需求上漲很厲害,而且不可預(yù)測(cè),很多需求不在總體規(guī)劃里。與此同時(shí),業(yè)務(wù)自有服務(wù)器在空閑時(shí)間段負(fù)載比較低,一般主要是白天比較忙。這樣的話,他們的現(xiàn)有資源其實(shí)是能夠去支撐新增的一些數(shù)據(jù)分析業(yè)務(wù)的。
所以,考慮到平臺(tái)在擴(kuò)容的時(shí)候是沒(méi)有辦法跟上業(yè)務(wù)的發(fā)展腳步的。為了能盡快滿足業(yè)務(wù)數(shù)字化建設(shè)需求,我們計(jì)劃為這些業(yè)務(wù)做有化部署,基于Spark做私有化部署的時(shí)候,我們遇到一些問(wèn)題。
首先,如果按照我們自己標(biāo)準(zhǔn)的模式為每個(gè)用戶去獨(dú)立部署一個(gè)Spark on Yarn的話,管理復(fù)雜度就太高了。我們可能會(huì)管很多個(gè)集群的Spark on Yarn,這樣的管理成本是無(wú)法支撐的。另外,部分用戶服務(wù)器已經(jīng)部署了HBase on Hadoop,這些集群不允許我們部署Hadoop也不允許我們?cè)谏厦娌渴餒base,而且不能使用已有的Hadoop。這樣就給Spark體系增加了很多難度。并且,業(yè)務(wù)用戶希望使用這種純SQL分析數(shù)據(jù),如果是這樣,我們會(huì)需要添加類(lèi)似于Kyuubi的工具,我們需要為了滿足一個(gè)需求添加很多組件,這樣的話多個(gè)集群的管理復(fù)雜度會(huì)非常高。還有一種方式就是我們不采用on Yarn的方式,采用Spark Standalone模式,其實(shí)部署起來(lái)相對(duì)還好,只使用Spark + Alluxio還不錯(cuò)。
但這種方式的問(wèn)題是,如果我們采用Spark per job作業(yè)模式,它的并發(fā)度是有限的。如果我們給一個(gè)通用值,它并發(fā)度是一個(gè)查詢起一個(gè)job,并發(fā)度是比較低的,可能同時(shí)只能并發(fā)幾個(gè)。而且Spark配置復(fù)雜度偏高,對(duì)于SQL用戶來(lái)說(shuō)不是很友好,還需要配置內(nèi)存大小,executor數(shù)目,或者Dynamic allocate限制參數(shù)。如果不采用Spark per job采用單Session的模式,又沒(méi)有辦法在多任務(wù)間做優(yōu)先級(jí)隔離,無(wú)法對(duì)一個(gè)業(yè)務(wù)的多個(gè)SQL進(jìn)行編排。
我們的思路是希望使用Presto+Alluxio做一個(gè)輕量級(jí)的數(shù)據(jù)分析,基于Presto Iceberg native connector,直接去操作存儲(chǔ)在Alluxio上面的Hadoop catelog表,只需要加Presto + Alluxio兩個(gè)組件,我們就可以完成整個(gè)ETL的過(guò)程。我們用了兩套mount系統(tǒng):第一套是比較傳統(tǒng)的Alluxio直接去mount平臺(tái)的HDFS;第二套是Alluxio structure data service(結(jié)構(gòu)化數(shù)據(jù)服務(wù))mount hive表,對(duì)于用戶集群來(lái)說(shuō),他看到的hive表跟平臺(tái)這邊的hive表是一樣的。Mount的好處是可以將數(shù)據(jù)透明地映射到Alluxio命名空間之內(nèi),通過(guò)Hive Table load提前把數(shù)據(jù)加載至Alluxio緩存中,增加數(shù)據(jù)讀取性能。所有的中間過(guò)程只需要Presto以must cashe的方式寫(xiě)入Alluxio本地,加工完之后,就可以把這個(gè)數(shù)據(jù)最后的結(jié)果數(shù)據(jù)寫(xiě)回平臺(tái)的hive。整個(gè)架構(gòu)比較簡(jiǎn)單的,只需要兩個(gè)組件,每臺(tái)機(jī)只要起兩個(gè)進(jìn)程,沒(méi)有額外的負(fù)擔(dān)。
而且用戶可以通過(guò)JDBC或者是Command line兩種形式訪問(wèn)Presto,并且用戶可以通過(guò)選擇性的persist Iceberg Hadoop table來(lái)授權(quán)給其他集群用戶訪問(wèn)中間數(shù)據(jù)。通過(guò)Alluxio的統(tǒng)一命名空間設(shè)計(jì),用戶看到的hive table、Iceberg table是完全一致的,實(shí)現(xiàn)了多個(gè)集群之間的透明管理。
在這個(gè)輕量級(jí)數(shù)據(jù)分析棧內(nèi),我們只需要用在戶集群搭建兩個(gè)組件就可以滿足需求。因?yàn)橛脩艋赑resto以純SQL的方式完成數(shù)據(jù)分析,體驗(yàn)比較好。目前我們用戶喜歡用JDBC的方式去連接,所以暫時(shí)不需要提供更多可視化工具。如果需要,只要在我們現(xiàn)有的可視化工具里配置鏈接就行。Alluxio mount平臺(tái)HDFS用于私有化數(shù)據(jù)共享,SDS mount平臺(tái)Hive用于共有數(shù)據(jù)訪問(wèn)及性能加,基于Presto Iceberg connector的hadoop catalog mode這種模式,可以采用只寫(xiě)緩存的方式在本地完成ETL。Alluxio全部使用的掛載磁盤(pán)的方式來(lái)保證緩存空間足夠容納數(shù)據(jù)分析中間數(shù)據(jù),最終數(shù)據(jù)持久化至平臺(tái)HDFS。Alluxio在寫(xiě)入的時(shí)候會(huì)使用三副本的策略,保證緩存數(shù)據(jù)的可用性。
今天的分享就到這里,謝謝大家。