快手?jǐn)?shù)據(jù)成本白盒化治理實(shí)踐
一、數(shù)據(jù)治理體系
和行業(yè)大部分公司一樣,快手?jǐn)?shù)據(jù)治理也是分為四大部分:成本、質(zhì)量、效率和安全。
1. 效率
分為數(shù)據(jù)開發(fā)效率和數(shù)據(jù)消費(fèi)效率。開發(fā)效率主要關(guān)注模型開發(fā)效率,消費(fèi)效率主要關(guān)注模型是否足夠易用,查詢響應(yīng)是否足夠快。
2. 安全
同樣也是分為生產(chǎn)階段的安全、還有消費(fèi)階段的安全。
3. 質(zhì)量
分為避免發(fā)生、主動(dòng)發(fā)現(xiàn)、故障結(jié)果、故障復(fù)盤。
- 避免發(fā)生:在設(shè)計(jì)、開發(fā)、測(cè)試和驗(yàn)收環(huán)節(jié),是否符合規(guī)范。
- 主動(dòng)發(fā)現(xiàn):出了問題之后,一定是我們自己先發(fā)現(xiàn),而不是用戶告訴我們。首先要做到監(jiān)控覆蓋全面,其次還要實(shí)現(xiàn)有效的告警,確認(rèn)告警的有效率,是非常關(guān)鍵、也是最難的部分。
- 故障結(jié)果:各個(gè)級(jí)別故障數(shù)量,是否在預(yù)期范圍內(nèi),我們對(duì)故障是容忍的,只要控制在一定數(shù)量?jī)?nèi)。
- 故障復(fù)盤:首先,復(fù)盤要足夠深刻,抓住問題本質(zhì)、找到共性。其次,復(fù)盤會(huì)產(chǎn)生很多待改進(jìn)問題,這些問題是否被及時(shí)解決了。
4. 成本
數(shù)據(jù)成本由三部分組成:存儲(chǔ)成本、計(jì)算成本、流量成本。
- 存儲(chǔ)成本:存儲(chǔ)效率是白盒化的重點(diǎn):壓縮比、壓縮性能、副本數(shù)。壓縮比關(guān)注存儲(chǔ)密度,壓縮性能關(guān)注壓縮耗時(shí),副本數(shù)關(guān)注能否用較少的副本存儲(chǔ)數(shù)據(jù),確保數(shù)據(jù)不丟失。
- 計(jì)算成本:CPU 平均利用率衡量資源調(diào)度能力。如果調(diào)度能力不行,很容易出現(xiàn)負(fù)載不均,可能部分機(jī)器打滿,另一部分卻很空閑,導(dǎo)致集群整體利用率上不去。單 CU 處理數(shù)據(jù)量衡量引擎算力水平,隨著我們不斷去優(yōu)化計(jì)算引擎,單 CU 處理的數(shù)據(jù)量也會(huì)隨之升高。
- 流量成本
本次分享主要是講成本部分,我們通過(guò)三個(gè)白盒化實(shí)現(xiàn):引擎白盒化 + 數(shù)倉(cāng)白盒化 + 工具白盒化。
二、引擎白盒化
“引擎白盒化”,是一個(gè)具體的項(xiàng)目代號(hào),這個(gè)項(xiàng)目包含很多優(yōu)化點(diǎn):HBO 自動(dòng)化調(diào)參、壓縮算法替換、引擎算子分析……
1. HBO 自動(dòng)調(diào)參
什么是 HBO 自動(dòng)調(diào)參?可以想象一下,在沒有 HBO 之前,調(diào)參主要通過(guò)人工完成的,但有三大弊端:
難度高:對(duì)于一個(gè)普通數(shù)據(jù)開發(fā)者來(lái)說(shuō),這無(wú)疑是一件很難做好的事情。首先需要理解引擎原理,分析作業(yè)的幾十個(gè)指標(biāo),找到性能問題,再調(diào)參,還不一定能調(diào)好。
易失效:隨著時(shí)間推移,計(jì)算邏輯、數(shù)據(jù)內(nèi)容可能早已發(fā)生改變,之前的調(diào)參過(guò)一段時(shí)間就失效了。
成本大:可以想像一下,對(duì)幾萬(wàn)、十萬(wàn)個(gè)作業(yè)進(jìn)行人工調(diào)參,基本是不可能完成的事情。
HBO 的出現(xiàn)就可以很好地解決這三大問題,它是通過(guò)分析任務(wù)運(yùn)行歷史,自動(dòng)優(yōu)化作業(yè)執(zhí)行參數(shù),從而使作業(yè)一直處于貼近最優(yōu)的狀態(tài)。
HBO 為什么可以提升性能、降低成本?主要通過(guò)三個(gè)方面來(lái)實(shí)現(xiàn)的:
(1)合理資源配額:通過(guò)識(shí)別作業(yè)對(duì) CPU 和內(nèi)存的需求,自適應(yīng)擴(kuò)縮容,防止錯(cuò)配。
(2)優(yōu)化任務(wù)分片:通過(guò)分析任務(wù)時(shí)長(zhǎng),靈活調(diào)整分片參數(shù),以防止過(guò)短或過(guò)長(zhǎng)。
(3)任務(wù)優(yōu)化功能參數(shù):通過(guò)調(diào)整小文件合并、壓縮算法、Broadcast 等參數(shù),以提升性能。
HBO 調(diào)參過(guò)程就是數(shù)據(jù)驅(qū)動(dòng)的過(guò)程:
第1步,構(gòu)建畫像,需要采集幾十個(gè)決策指標(biāo),指標(biāo)的質(zhì)量直接決定了 HBO 效果,需要的是嚴(yán)謹(jǐn)。
第2步,參數(shù)粗調(diào),通過(guò)數(shù)據(jù)指標(biāo)+預(yù)設(shè)規(guī)則,進(jìn)行首次粗調(diào)參,粗調(diào)時(shí)會(huì)盡量的保守,比如:CPU/內(nèi)存會(huì)盡可能多預(yù)留一些,以防止運(yùn)行變慢。
第3步,參數(shù)下發(fā),將調(diào)參的結(jié)果下發(fā)給各個(gè)任務(wù),下發(fā)之后,下一個(gè)周期就會(huì)產(chǎn)生影響。
第4步,參數(shù)精調(diào),粗調(diào)之后,我們能感知調(diào)參效果,根據(jù)最新反饋進(jìn)一步精調(diào)、再精調(diào)。
以上列舉了部分調(diào)參列表,供參考。接下來(lái)我們看看第二個(gè)優(yōu)化項(xiàng),存儲(chǔ)壓縮算法替換。
2. 壓縮算法替換
先看看快手大數(shù)據(jù)存儲(chǔ)現(xiàn)狀:
- 技術(shù)選型:湖倉(cāng)的底層存儲(chǔ)是 PARQUET + GZIP。
- 數(shù)據(jù)規(guī)模:新增 PB / 存量 EB。
- 數(shù)據(jù)讀寫:讀寫比大于 20:1,讀取數(shù)據(jù)量遠(yuǎn)高于寫入數(shù)據(jù)量,所以我們會(huì)更加關(guān)注解壓性能,而壓縮性能稍微差點(diǎn),是可以接受的。
- 存儲(chǔ)周期:很多數(shù)據(jù)存儲(chǔ)周期比較長(zhǎng),甚至是永久存儲(chǔ),滿足審計(jì)相關(guān)的需求,所以對(duì)于存儲(chǔ)系統(tǒng)來(lái)說(shuō),壓縮比永遠(yuǎn)是我們首要考慮的。
在壓縮算法這塊,快手選型是 GZIP,縱觀行業(yè)里的很多公司,一開始也都是 gzip,不過(guò)這些公司都逐步切換到了 zstd,因此為他們節(jié)省了大量的成本。以上圖片列舉了:亞馬遜、推特、優(yōu)步幾家公司在推特上的一些討論。
Zstd 既有著和 zlib 相當(dāng)?shù)膲嚎s率,同時(shí)還有媲美 snappy 的壓縮性能,可謂是集合了兩者的優(yōu)勢(shì)。
另外,我們也在線上進(jìn)行了實(shí)測(cè),壓縮率提升 3%~12%,壓縮級(jí)別越高,壓縮率也就越高。Zstd 壓縮級(jí)別分為 1-22,根據(jù)我們的觀察,壓縮級(jí)別超過(guò) 12 之后,壓縮率提升的就不是很明顯了,所以我們最終選擇的壓縮級(jí)別,最高不超過(guò) 12。
此外,我們還做了很多其它的測(cè)試,穩(wěn)定性、準(zhǔn)確性、兼容性,這三方面都沒有問題。提示一下:zstd-jni 1.5.0 以下的版本有不少的 bug,建議升級(jí)到 1.5 以上,完全向下兼容。
3. 引擎算子分析
什么是引擎算子分析?通過(guò)對(duì) Spark 引擎進(jìn)行多視角、多維度深度剖析,提升對(duì)引擎的認(rèn)知,使算力可解釋、明確算力瓶頸、挖掘算力潛在優(yōu)化點(diǎn)。
通過(guò)不同的視角進(jìn)行深度剖析,在不同的視角下,能發(fā)現(xiàn)不一樣的問題,找到不同的潛在優(yōu)化點(diǎn)。本次介紹最重要的 3 個(gè)分析視角,分別是執(zhí)行過(guò)程視角、物理算子視角、UDF 函數(shù)視角。
(1)執(zhí)行過(guò)程視角:將計(jì)算劃分為十大過(guò)程,分析這十大過(guò)程的構(gòu)成、資源開銷、時(shí)間開銷。
(2)物理算子視角:物理算子和邏輯算子有著對(duì)應(yīng)關(guān)系,一個(gè)邏輯算子有多種不同物理實(shí)現(xiàn),在不同的場(chǎng)景下,匹配不同物理算子。物理算子內(nèi)部實(shí)現(xiàn)是否高效,以及是否被正確使用,都對(duì)性能有重大影響。
(3)UDF 函數(shù)視角:對(duì)幾百個(gè) UDF 函數(shù)使用情況進(jìn)行分析,既包含引擎內(nèi)置的,也包含用戶實(shí)現(xiàn)的。
引擎理解同樣也是數(shù)據(jù)驅(qū)動(dòng)的,拆解引擎需要用到四大數(shù)據(jù)源:
(1)QueryPlan:通過(guò)解析 SQL,生成執(zhí)行計(jì)劃,從而對(duì)算子進(jìn)行分析。
(2)StackTrace:用于分析調(diào)用堆棧,生成直方圖、火焰圖,進(jìn)行性能分析。
(3)EventLog:作業(yè)在運(yùn)行過(guò)程中生成的 DAG 圖譜以及各種指標(biāo),這對(duì)引擎理解也有極大的幫助。
(4)GcLog:最后是 GcLog,主要用來(lái)精準(zhǔn)分析內(nèi)存用量,減少 OOM 發(fā)生的概率。
接下來(lái)看一組數(shù)據(jù),以上是對(duì)執(zhí)行過(guò)程的分析,我們看看耗時(shí)最大的四個(gè)過(guò)程,有了數(shù)據(jù)之后,只需要通過(guò)進(jìn)一步下鉆分析,就能找到優(yōu)化方向:
數(shù)據(jù)掃描:占比最大,超過(guò) 30%,有點(diǎn)超出預(yù)期,說(shuō)明潛在優(yōu)化空間是非常大的。
數(shù)據(jù)交換:占比第二,大概 20%,也是非常高的。
數(shù)據(jù)聚合:占比第三,大概 15%。
UDF 調(diào)用:占比第四,大概 14%。
Aggregate:整體比較健康。
Join:SortMergeJoinExec 性能差,但占比 95.3%,可通過(guò) HBO 調(diào)參轉(zhuǎn)換BroadcastHashJoinExec。
Scan:數(shù)據(jù)讀取和壓縮占比低,而數(shù)據(jù)處理占比 75.94%,后續(xù)主要考慮如何提升數(shù)據(jù)處理的效率(包含 schem 處理,行列轉(zhuǎn)換等)。
首先,Json 處理占了 1/3 還要多,這是非常不健康的,這是重點(diǎn)要去解決的。第一,要優(yōu)化 JSON 處理性能,第二,我們也得看看為什么有這么多的 JSON 要處理?肯定有哪里不對(duì)勁。
其次,平臺(tái)公共 UDF,整體看起來(lái)還算可以。
最后,業(yè)務(wù) UDF,可以看到占比也很高,也是需要重點(diǎn)去解決的。
當(dāng)我們有了數(shù)據(jù)、看清了現(xiàn)狀,接下來(lái)應(yīng)該如何應(yīng)對(duì)呢?
(1)我們需要去做分析,判斷。判斷是否合理?是否有優(yōu)化空間?空間有多大?
(2)需要確保使用方法正確。如果有一輛好賽車,但是不懂駕駛,就很難發(fā)揮出應(yīng)有的性能。
(3)可以看看某些零部件,是否有替代方案。例如 JSON 處理,壓縮算法。
(4)如果以上都解決不了,那就只能自己動(dòng)手去重構(gòu)某些零部件了,尤其是一些關(guān)鍵零部件。
更多的優(yōu)化,也還在進(jìn)行當(dāng)中。
三、數(shù)倉(cāng)白盒化
1. 數(shù)倉(cāng)架構(gòu)度量
講數(shù)倉(cāng)白盒化之前,我們必須先要弄清楚,好的數(shù)倉(cāng)標(biāo)準(zhǔn)是什么樣的?只有搞清楚了數(shù)倉(cāng)架構(gòu)的量化指標(biāo),才能指導(dǎo)我們進(jìn)行優(yōu)化:
完整度:衡量數(shù)據(jù)模型建設(shè),是不是足夠完整、通用,滿足的需求是不是足夠廣泛。其實(shí)就是分析跨層引用多不多?跨層引用過(guò)多,數(shù)倉(cāng)模型一定不是完整的。
復(fù)用度:主要看三個(gè)指標(biāo)(引用系數(shù)、重復(fù)計(jì)算、鏈路深度)。
規(guī)范性:這是基礎(chǔ)要求,但做好并不容易,尤其是一開始沒做好,后續(xù)想要撿起來(lái),會(huì)非常困難。
2. 如何減少重復(fù)計(jì)算
先來(lái)看一個(gè)相似算子的示例。圖中給出了三個(gè)查詢,拆解為語(yǔ)法樹之后,不難發(fā)現(xiàn),這其中隱藏了非常多的相似代碼片段。圖上用了四種不同顏色,進(jìn)行標(biāo)識(shí),相同的顏色代表此部分計(jì)算邏輯是相似的,這些相似片段,通常都會(huì)帶來(lái)數(shù)倍資源開銷。
如何識(shí)別相似的代碼片段呢?
第1步,獲取任務(wù)列表,我們要獲取到所有執(zhí)行任務(wù)的 SQL。
第2步,生成執(zhí)行計(jì)劃。
第3步,逐層算子簽名,通過(guò)后序遍歷 AST,逐層向上展開,直到完成整棵數(shù)的簽名,得到簽名集合。
第4步,重復(fù)算子識(shí)別,通過(guò)簽名碰撞,去發(fā)現(xiàn)重復(fù)的算子。
第5步,計(jì)算算子代價(jià),代價(jià)越高的重復(fù)算子,就越應(yīng)該抽象、沉淀下來(lái)。
第6步,合并重復(fù)算子,提升處理速度,降低成本。
這是我們內(nèi)部的一組數(shù)據(jù),直觀的感覺就是重復(fù)比例有點(diǎn)大??梢钥吹骄酆系南嗨扑阕舆_(dá)到了驚人的 43%,這是非常之高的,連接算子也達(dá)到了 23%,最后,還有 4.5% 的 INSERT 算子是相似的,INSERT 是最后輸出的模型,這說(shuō)明了有 4.5% 的模型是相似的。如果說(shuō),我們不去自動(dòng)干預(yù)、自動(dòng)治理,只會(huì)越來(lái)越惡化。
當(dāng)我們識(shí)別了相似算子,看清了現(xiàn)狀,那么到底有什么價(jià)值呢?主要有三個(gè):
指導(dǎo)治理:向用戶展示當(dāng)前現(xiàn)狀,并給出整改優(yōu)化建議.
輔助開發(fā):主要包含模型選擇和優(yōu)化。
查詢加速:通過(guò)自動(dòng)物化視圖,實(shí)現(xiàn)查詢加速,這個(gè)過(guò)程對(duì)用戶是完全透明的。
3. 如何降低鏈路層級(jí)
想要降低鏈路層級(jí),我們得先了解現(xiàn)狀。上圖是線上某條生產(chǎn)鏈路,展示的是任務(wù)依賴關(guān)系??梢垣@得一些信息:首先是,鏈路層級(jí)非常深:達(dá)到了驚人的 39 層。其次是,跨層依賴非常多:可以明顯看出來(lái)很多末尾的 ADS 節(jié)點(diǎn),甚至?xí)蕾囎钤搭^ODS。這也間接導(dǎo)致了很多問題,例如:數(shù)據(jù)及時(shí)性差、生產(chǎn)成本高、數(shù)據(jù)質(zhì)量難以控制。
為什么會(huì)出現(xiàn)這種現(xiàn)象?既要滿足快速變化的業(yè)務(wù)需求,又要不斷地抽象和沉淀,還要確保不出現(xiàn)質(zhì)量問題。既要又要還要,通常來(lái)說(shuō),這三者很難同時(shí)兼顧,所以隨著時(shí)間變化,導(dǎo)致數(shù)倉(cāng)劣化。
那么怎么去改變現(xiàn)狀呢?第一種解決方案是機(jī)器輔助治理。首先,通過(guò)構(gòu)建算子級(jí)血緣,還原數(shù)據(jù)加工邏輯。其次,分析并發(fā)現(xiàn)模型中的不合理,生成整改優(yōu)化建議。最后,由用戶根據(jù)建議去優(yōu)化。
第一種解決方案,只是用于短期治理,并沒有從根本解決問題。那么終極方案是什么呢?我認(rèn)為是邏輯層和物理層解耦,將邏輯模型和物理模型完全分離開來(lái)。
邏輯層:數(shù)據(jù)開發(fā)者只需要根據(jù)業(yè)務(wù)需求去設(shè)計(jì)邏輯模型,而完全不用理會(huì)底層實(shí)現(xiàn)。
物理層:物理模型和鏈路,完全由機(jī)器自動(dòng)化構(gòu)建,并且根據(jù)邏輯模型的變化,不斷的迭代和調(diào)整,使數(shù)倉(cāng)一直處于貼近最優(yōu)的狀態(tài)。
4. 常規(guī)治理自動(dòng)化
首先我們不得不聊一下現(xiàn)狀:治理屬于一種事后清理工作,善后工作,大家普遍不會(huì)太重視,或者說(shuō)優(yōu)先級(jí)低,沒時(shí)間處理。做數(shù)據(jù)治理平臺(tái)的同學(xué)無(wú)一例外,都遇到了這個(gè)問題,就是推不動(dòng)業(yè)務(wù)去治理。
那到底應(yīng)該怎么辦呢?我們的答案是:常規(guī)治理自動(dòng)化!但是自動(dòng)化治理,面臨的最大挑戰(zhàn)就是怎么確保自動(dòng)的過(guò)程中可靠安全?萬(wàn)一刪錯(cuò)了數(shù)據(jù)怎么辦?萬(wàn)一導(dǎo)致了故障怎么辦?其實(shí)并沒那么可怕,再難的事情,只要有體系化的保障,就不用害怕,我們給出的方案是五步法自動(dòng)治理:
制定標(biāo)準(zhǔn):自動(dòng)化治理一定要有嚴(yán)格的標(biāo)準(zhǔn),只有形成了標(biāo)準(zhǔn),才有可能自動(dòng)化,這是先決條件。
問題識(shí)別:根據(jù)標(biāo)準(zhǔn)、根據(jù)規(guī)則去識(shí)別生產(chǎn)待治理的問題。
質(zhì)量檢驗(yàn):第一道防火墻,通過(guò)波動(dòng)檢測(cè)、交叉驗(yàn)證等方式阻斷部分問題發(fā)生。
治理預(yù)告:第二道防火墻,對(duì)于非常 critical 的治理動(dòng)作,通過(guò)治理預(yù)告,讓用戶幫助阻攔問題。
快速回滾:第三道防火墻,即使出現(xiàn)了問題,也能快速回滾。所有的治理動(dòng)作,必須是可以回滾的,否則就不能納入到自動(dòng)化范圍。
四、收益分析
數(shù)據(jù)存儲(chǔ)壓縮率:提升 5%,計(jì)算資源收益:提升 16%,作業(yè)運(yùn)行時(shí)長(zhǎng):和計(jì)算資源收益相當(dāng),縮短 14%。此外,作業(yè)失敗率、GC 時(shí)間、OOM 等也有不同程度的下降
五、未來(lái)規(guī)劃
未來(lái)工作更多的是延續(xù),因?yàn)楹芏喙ぷ鞑艅傞_始起步,還比較淺??偟膩?lái)說(shuō),有這么幾件事:
數(shù)據(jù)壓縮:之前主要是替換壓縮算法,這個(gè)紅利已經(jīng)吃完了。接下來(lái)還要再繼續(xù)提升的話,就需要在動(dòng)態(tài)壓縮、編碼等方面下功夫。
數(shù)倉(cāng)架構(gòu):前面我們講的數(shù)倉(cāng)白盒化,很多工作都才剛開始,特別是在模型設(shè)計(jì)、模型生產(chǎn)等方面。
深度范圍:進(jìn)一步提升引擎白盒化治理深度。
下代技術(shù):要想在效率和成本上產(chǎn)生突破,必須要布局下一代技術(shù),跳出我們現(xiàn)有的認(rèn)知,在技術(shù)范式上取得進(jìn)展。