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