雲音樂實時數倉建設以及任務治理實踐

韓楠發表於2023-01-18



 本期分享嘉賓 


汪磊  

杭州網易雲音樂科技有限公司

資料平臺開發專家

【嘉賓介紹】 汪磊, Zeppelin Contributor ,雲音樂資料平臺開發專家,資料平臺組計算平臺負責人。 2013 年加入網易,參與過易信、雲音樂等產品的數倉建設,目前主要負責雲音樂離線、實時、機器學習等統一資料平臺建設工作。

分享概要:

1.雲音樂實時相關業務現狀和資料規模

2.分割槽流表技術介紹

3.資料任務治理實踐

4.未來規劃

以下為大會演講實錄部分:

隨著業務的發展,數 據流量 大, 以及實時數倉的應用越來越廣泛,音樂實時數倉的流量越來越大,使用者也越來越多,超大 流量的訊息佇列對整體頻寬資源、下游的消費任務的穩定性以及計算資源都帶來了巨大的挑戰。為了解決這一問題我們升級了 Flink 原生的實時流表的方案擴充套件實現了流表的分割槽支援,大大降低了整體的流量頻寬和計算資源的消耗。

底層技術的升級帶來了大量任務的升級改造、業務發展太快,平臺需要下線的廢棄資料任務也會越來越多,平臺開發水平層次 不齊 、大量的資料任務配置,都需要最佳化升級等等,這些都是業務平臺開發日常面臨的繁瑣、難以推進的且很難說明價值的工作。為了更好地觸達使用者,系統化解決日常的資料任務治理工作,我們設計了一套系統化、流程化、   可審計跟蹤的的大資料任務治理方案來解決日常任務治理工作。





雲音樂實時相關業務現狀和資料規模

首先介紹下雲音樂目前實時相關業務的一些現狀和資料規模,如下圖所示。

關於雲音樂實時數倉整體的架構,其實業界基本都差不多。資料來源主要為兩部分:

1.使用者行為日誌,從客戶端收集,透過訊息佇列歸檔到資料倉儲。 2. 業務資料的庫的資料,透過binlog訂閱來實時同步業務庫資料入倉。

實時數倉的建設大部分的點集中於以下兩個部分:  

第一部分即 ODS 到DWD明細層。明細層是實時數倉的基礎,不做任何的聚合操作,將原始的使用者日誌清洗成設計好的資料統計模型;整合業務領域語言,擴充套件統一的業務統計指標,統一資料口徑,避免資料不一致的問題,降低資料倉儲使用門檻。

再上層即DWD 到DWS 聚合層,在實時數倉的建設中,DWS層聚合的成本非常高。實時計算大部分只會做一些很輕量級聚合,比如分鐘級、小時級別的聚合,按需建設,有需求時會將這一層的資料落到現在比較流行的OLAP引擎當中,比如 CK,來滿足一些業務定製化的實時的資料查詢需求。

其次是ADS層,應用資料層。這層資料完全根據業務需求進行開發,比如實時的日活大盤,我們一般會查詢DWD的資料,聚合UV資料,然後將結果寫入到KV當中,供前端查詢。

再比如在一些直播的Push場景中,當主播上線時,需要實時地查詢主播的線上的粉絲,來傳送push訊息,這個查詢需要多個業務庫的資料表關聯查詢出結果,但是在生產環境中,為了保障線上服務的穩定性我們不可能直接從業務庫執行很複雜的關聯查詢,而是需要透過binlog將業務庫的資料實時同步到OLAP引擎中,透過OLAP引擎查詢出最終的結果觸達使用者。這一場景是Binlog入倉在實時場景中的一個典型應用。

音樂相關業務現狀和規模

由於 使用者基數越來越大, 業務線 越來越多 開發對實時平臺的需求也越來越多, 我們在 平臺 建設中也遇到 諸多問題,以下幾類較為典型

1. 開發門檻高

Flink 經過多年的發展,Flink SQL不斷最佳化,Flink上手的門檻在降低,但是難於運維調優,SQL遮蔽了很多細節,遇到問題,使用者往往無從下手。Flink本身的成熟度也還在發展當中,比如在打狀態任務上,存在很多的穩定性問題。

這些年大資料領域的儲存中介軟體層出不窮,如:Clickhouse、Drios、Kafka等等,都有著不小的學習成本和門檻,整體處於一個易上手難精通的狀態,在音樂這種大的業務體量下,很多問題都會被暴露出來。

再加上還有一些使用者背景的問題,我們使用者很多都不是專門資料背景的,而是前後端的應用開發,在此背景下平臺的使用和運維門檻問題更加凸顯。

2.模型設計問題。

在實時數倉設計上,需考慮一些效能問題。若按照離線數倉直接設定,一些大的資料量的實時流表,會導致Kafka的壓力非常大,頻寬壓力、下游任務的處理壓力也會非常大。

所以還需權衡效能和模型設計上的一些問題,初期讓人很是頭痛。下文會講到分割槽流表,它主要用來解決該問題。

3.任務運維問題。

任務指標:任務的  metrics  指標非常專業,很多使用者理解起來門檻很高。比如 Kafka RocksDB  的一些指標, 專業度非常高, 難於理解。

任務的流量波動,外部儲存的使用成本,機器的負載,其中任何一環出現問題,任務的穩定性都會受其影響,定位問題非常 困難。

任務狀態問題:我們不知道一個 正常執行的 任務   到底還在不在服務 業務 ,因此任務治理上非常難,存在一定的問題。

4.任務治理問題。

比如離職員工任務問題,存在大量的離職殭屍任務;任務價值閉環問題,任務花費這麼大的資源是否真的值得;資源配置和效能問題,任務的資源配置是否合理。

分割槽流表技術介紹

關於在實時數倉中遇到的一些問題,我們構建了分割槽流表技術以解決模型設計的效能問題。

分割槽流表技術建設

如果按照離線數倉的思想構建數倉模型,模型設計和任務穩定性之間需要權衡,以下就離線和實時數倉的一些區別加以對比。

離線:  

  • 相比實時場景對資料量、資源消耗敏感度較低。

  • 最佳化手段多:分割槽、分桶、資料有序寫入等,可以高效地過濾掉無效的資料。

  • 儲存穩定性:HDFS等落地儲存,資料量的增長對穩定性的影響相對較小。

實時:

  • 對任務延遲非常敏感,資料量任務的穩定影響較大,從而導致不任務SLA達不到業務需求。

  • 最佳化手段少:以KAFKA為基礎的實時流表,幾乎沒有過濾資料的高效策略。

  • 儲存穩定性:資料量的增長對KAFKA的穩定性影響較大,多一個消費,KAFKA效能/網路頻寬就多一份壓力。

總體而言,在離線場景上,大家更關注於業務模型的設計,對於效能的敏感度非常低。然而在實時上則不同,對於任務的延遲非常敏感,整體上很難做到很高效的過濾策略。

整體架構

我們的目標是希望讓使用者做到離線,能夠以離線的模型達到業務的需求,同時又不犧牲太多效能,保證Kafka 的壓力是可控的。  

我們初期希望在 ODS到 DWD 層能夠做一些最佳化,為了解決上述問題,犧牲了模型的統一性加以解決,畢竟效能、穩定是第一,初期還是以效能保障為第一要素。

問題的解決上,我們的方法是什麼? 各大公司也有相應方案,比如做一些日誌分發,我們初期也是將 ODS 層的資料分發為不同的訊息佇列。

初期架構

比如離線裡面有一個表叫 user action,實時的ODS層資料表的schema也是一樣,但我們會將其分成比如Queue1、Queue2、Queue3…..Queue10,不同的訊息佇列儲存著不同的業務主題的資料,看似有點奇怪,但它有效地解決了很多流量帶來的效能問題,當然也存在著一些問題:

1. 使用門檻高。使用者在用這些表時,會按不同的業務需求分成 10 個 topic。不同的佇列裡有不同的流表。使用者在使用之時有一定門檻,首先需要查每一個表記錄的是什麼業務主題的資料。

2. 模型不統一。我們與離線的模型肯定是不統一的,導致使用者在使用實時數倉和離線數倉有很大的不同,帶來很多體驗問題,也不方便後續批流一體數倉的建設。

3. 複用成本高。開發代價低,複用程度低,每個分發都要單獨地構建訊息分發的程式。

4. 運維調整困難。比如要想將 Queue10 流量大了再做一次分割,其成本實則很高。需要通知到所有下游的任務去重啟任務,重新調整程式碼,整體成本太高。

分割槽流表

為解決上述問題,我們在2021年年底開啟了分割槽流表的建設。  

分割槽流表原理上很簡單,希望做到在流表側也能夠有著比較好的手段做來有效的做資料過濾,減少資料的讀取,所以我們聯想到了Hive分割槽表的結構,希望在流表上也能做到和HIVE分割槽表一樣的分割槽效果,減少流量的吞吐。

雖然做不到更高效地做到分桶或者有序的過濾這種策略,但是在分割槽上仍可做一做。因此我們按照不同的行為,按照表欄位做了一些分割槽策略,不同行為日誌分別儲存到不同的topic當中。在流表的 case 上,一個流表對應多個分割槽,每個分割槽儲存不到的業務資料,做到和離線模型統一,同時還能保證效能。  

在使用者去讀的時候,我們會根據使用者的查詢條件進行分割槽下推,拿到對應的 topic,減少不必要的資料讀取。

流表分割槽的功能直接整合在我們的Source 和 SINK的Connector當中,因此其複用成本非常低。使用者只要 insert 分割槽流表,自然就會按照定好的分割槽規則寫到不同的 topic 裡,能夠做到和普通流表一樣的使用,所以很容易推廣複用,在任何層次或任何業務上均可使用分割槽流表來減少資料的吞吐。

此外,在運維工作上我們也會做很多工作,可以做到執行時的動態的分割槽修改。

產品實現

我們是如何實現的?下圖左側為產品圖,在流表上會配一些分割槽規則,它是哪個topic, 其管理在源資料端可以管理到。  

上圖右側為整體方案,參考了 Hive 的方案。因為離線資料的分割槽表是相對靜態的,無需考慮其變化,而且批任務一般是排程執行,分割槽發生變厚,任務下一次再去讀它能感知到即可。

但是在實時情況下則不同,任務都是常駐執行,需要感知分割槽的變化,並做出相應的調整,所以我們構建了一個 meta server, 它會與任務同步流表的分割槽規則,在SINK 側,實時程式會和meta server實時同步分割槽規則,根據訊息內容和分割槽規則選擇相應的topic進行寫入即可。同時寫入程式也會往meta server上報血緣,保證後續在meta server上能很好的監控到哪些任務在寫入資料,寫入的狀況如何,進而保證運維能夠監控到每個任務的狀態。

在 source 側相對複雜一些,同樣需要定時和meta server同步分割槽規則資訊,任務啟動時透過使用者的查詢條件請求meta server獲取正確的分割槽,進行分割槽剪枝。我們將分割槽計算的這一次操作的主要邏輯放在server端,用以保證後續若分割槽剪枝能力出現一些問題或變化時,能夠在 server 端自動去調整,直接把分割槽結果返回給source,而非改造引擎的程式碼,將改動多的邏輯中心化掉,減少後期維護的成本。  

在改造過程中我們也發現了一些問題,如果流表上有watermark的配置,Flink SQL程式碼中分割槽規則會下推不下去,Flink SQL的RBO的Rule對這種情況支援有一些問題。就此我們對Flink SQL原始碼也做了一些改造,新增了相應的Rule來支援這種情況下分割槽流表的分割槽下推。

為了感知分割槽的變化,source端也會和meta server不斷的同步分割槽關係,在分割槽規則發生變化時,source端也會重新請求meta server獲取最新的topic列表,讀取最新的資料,保障讀取資料的正確性,適配執行時動態地調整分割槽規則,降低整體的運維成本。同時我們也會上報讀取血緣到meta server,方便運維管理,也能在meta server監控到所有消費端的狀態。

如此一來,我們就完成了整個實時的分割槽流表建設工作時,使用者在建設實時數倉時多了構建實時分割槽的手段,根據其業務做一些細緻化的分割槽來保障整個數倉建模一致性的同時,也能保障效能。基本上不用過多的考慮其效能問題,只需要按照業務的需求和流量大小合理地設計分割槽即可。

分割槽流表技術建設-效果

主要的效果之一,即模型做到了統一。現在我們已經覆蓋了所有的音樂業務線,任務的穩定性問題也得到了徹底的解決。  

因為以前流表分發粒度很粗,使用起來成本很高,後期維護起來也很難,但是上了分割槽流表以後,我們可以做一些很細緻化的分割槽。根據業務的需求經驗與數倉去合作做很細緻化的分割槽,基於此一些任務減少了很多流量的讀取。  

歷史任務完成分割槽改造遷移以後,其實我們節省能有 700W+的成本。

我們的 Kafka 的流量也大大降低了,基本上2022年全年幾乎沒有采購一臺Kafka,本身現在 Kafka 的壓力也非常可控,總體而言達到了非常好的效果。

資料任務治理實踐

降本提效

2022年的經濟形勢也不是特別好,所以各大公司都在提降本提效,以下講述我們做任務治理上的一些實踐經驗,如何做降本提效。接下來主要講整體提效任務治理的思路。    

我們作為一個業務方的資料平臺,希望任務用得越合理越好。總體而言,整體工作,分為以下四個部分。

1.摸清現狀,高效治理。我們先梳理下線索,有的放矢,而非眉毛鬍子一把抓,以最小的人力獲取最好的治理效果。

2.清理無用任務。我們拿到現狀的時候,希望能夠用很少的人力,以高 ROI 的方式,做一些無用任務的清理。有些任務本身消耗了很多資源,但是產出的資料相關業務方已經不再使用了,就果斷加以清理。

3.最佳化資源配置。有些任務資源消耗很大,但是資料量很小,資源量和資料量不是很匹配,我們想辦法最佳化其資源的配置。

4.自動化,可持續。上述三部分,均屬於運動式的治理工作。長遠來看,實為內耗。我們在做完這份工作以後,實則希望能夠可持續、自動化地將治理的工作做到平臺化、常態化,此乃降本增效的終極目標,而非每年都做運動式的治理。

摸清現狀

摸清現狀後,主要為兩部分:儲存成本和計算成本。

儲存成本:我們有一個專門的平臺,能夠統計出所有資料的成本,即每個資料需要花費多少。

計算成本:這部分投入了更多時間、精力,我們會在每個任務執行完以後,將成本直接反饋到使用者那裡,使其對成本有感知。另外,摸清每個任務每次執行的消耗,後續即可挑一些高消耗的任務去做相應最佳化和治理。  

擁有了這些成本資料,我們會根據其任務的歸屬做一些部門的聚合統計,能夠讓部門感知到資料的花費情況,此後也可以進行反推,限制每個部門整體的資源使用。

再看下資料任務治理實踐中的任務下線。

任務下線

血緣:梳理可下線的任務,即根據血緣發現無用表、無用任務。

運維積極性:根據運維的積極性,比如一個任務經常報警,沒人管。


殭屍任務:對離職、轉崗或是長期不更新的一些任務,加以確認。

任務血緣:根據活動的資料,以及下游訪問記錄做一些任務血緣,判斷哪些任務無用。

基本上,我們是基於上述一套流程來加以操作的。   我們部門主要提供的是資料支援的工作,主要數倉在做下線的工作。整體成本上,我們上半年節省了 2000 萬左右, 佔20% 左右,還是較為可觀的。

最佳化

實時計算部分做技術配置最佳化,其實主要是在最佳化上。

1. 技術升級。我們將分割槽流表全部覆蓋,做了全面推廣及升級改造,其工作量非常之大。


2. 配置最佳化。對資源梳理後,即可獲取每個任務的消耗資源,挑出來做一些資源消耗比較大的任務進行治理最佳化,資源調整,或者看下其流量是否配置得合理。我們發現很多使用者對 Flink 任務的配置比較隨意,非常不合理。這部分也節省了不少成本。

3. 資源最佳化。針對一些任務做不同的定製化的資源配比,比如一些流量較小,IO操作比較多的任務,我們會將這類任務遷移到超售比例比較高的叢集的Label上,減少整體資源的消耗。YARN的資源排程管理目前還非常的粗,該部分未來會基於K8S做一些資源管理精細化的工作,保障整體的資源消耗。  

做完上述治理以後,實際的資源消耗從 80% 多下降到 50% 多,下降了30%,最佳化效果顯著。

可持續

可持續是我們正在做的事情,希望告別大掃除的運動式的治理,能夠做到資料治理的常態化、平臺化。


基於此我們構建了一個系統,用資料治理資料。我們平臺叫做公孫策平臺,會收集任務、數倉、資源等後設資料,然後透過後設資料配置一些規則,能夠透過規則發現一些不合理的任務,以及一些已經需要下線的,或是資源/需求不合理的任務。發現這些任務以後,結下來就是需要推動使用者主動去最佳化改造。  

如何推動使用者主動改造?我們利用配置的規則對所有任務的質量進行打分,雲音樂的技術中心有一個質量分機制,我們和集團統一質量分做整合,公示資料,去推動使用者。質量分每一個平臺老大都非常關注,會在全公司進行排名,所以只透過質量分的推動,使用者去主動地做治理改造,能夠完成一個閉環。

整體的工作效果,我們分為三個階段:

開發前,根據任務配置和行為加以分析,做一些配置的推薦,上線的流程卡點,以保證配置的合理性。

執行中:做一些質量的掃描,任務的上下線。哪些任務需要下線,哪些任務配置不合理,對於不合理的任務,推進開發進行上下線操作或者配置最佳化。

下線後:我們會收集治理效果,對效果做一些排行榜,形成激勵機制,以保證使用者能夠把任務治理作為一個常態化的工作。


未來規劃

關於開發門檻問題、資料鏈路追蹤、儲存選擇最佳化、開發經驗沉澱 等問題  

結合上述問題,我們希望能夠圍繞以下四點   做一個新的業務化的 低程式碼的開發工 解決 ,整體建設思路如下:

1.低程式碼:我們希望透過能夠透過一些低程式碼的方式來降低 Flink 的開發門檻。

2.端到端:從資料處理到下游服務,做統一的整合,希望把一些業務上封裝的服務作為儲存,遮蔽底層細節,回收服務的服務資料,閉環資料價值。

3.批流一體。與低程式碼的整合,其實今年也有很多公司在做,我們希望能夠透過自定義的一套 DSL 生成 Flink 的實時流程式碼和 spark 的離線程式碼,能做到批流一體一套業務業務邏輯表達,同時生成實時任務和離線任務,統一管理排程,整合lambda架構,降低整體開發成本。

4.場景化。我們希望在業務場景的基礎上,去打造達到符合上述三點的場景,解決使用者的共性問題。

以下為未來整體的架構規劃:

1.以資料模型為中心。

2.以配置化的方式作為主要開發手段。

3.上下游服務深度整合。

4.批流一體任務統一管理排程。

5.希望透過場景化解決我們 80% 通用的常見場景問題。

當然 80% 是拍拍腦袋隨便估的,28原則, 我們希望透過這個平臺,解決一些場景的共性問題。這個東西它還依賴於數倉本身的建模的完善,如果建模做得不好,其實我們很難做到低程式碼,因為業務邏輯很複雜,低程式碼就不太可能去實現。但是如果 DWD 層做得很完善,使用者就可以專注在業務場景的邏輯開發上,非常高效地完成業務開發,提升開發效率,降低開發門檻。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70016482/viewspace-2932510/,如需轉載,請註明出處,否則將追究法律責任。

相關文章