字節(jié)、阿里關(guān)于實(shí)時(shí)數(shù)據(jù)湖的應(yīng)用與解決方案總結(jié)
在海量數(shù)據(jù)下,依靠傳統(tǒng)數(shù)據(jù)庫(kù)和傳統(tǒng)實(shí)現(xiàn)方法基本完成不了,企業(yè)需要一種分布式的、高吞吐量的、延時(shí)低的、高可靠的實(shí)時(shí)計(jì)算框架。
下面將為大家分享字節(jié)跳動(dòng)、阿里2家企業(yè)在實(shí)時(shí)數(shù)據(jù)湖的方面的實(shí)踐應(yīng)用。
01 實(shí)時(shí)數(shù)據(jù)湖在字節(jié)跳動(dòng)的實(shí)踐
近兩年數(shù)據(jù)湖是一個(gè)比較火的技術(shù),從傳統(tǒng)的數(shù)倉(cāng)到數(shù)據(jù)湖,在過(guò)去 5 年里架構(gòu)演變得非常迅速。Hudi、Iceberg、Dalta Lake在業(yè)界被稱為數(shù)據(jù)湖三劍客。
目前,字節(jié)對(duì)數(shù)據(jù)湖的解讀,主要聚焦在數(shù)據(jù)湖的六大能力上:高效的并發(fā)更新能力、智能的查詢加速、批流一體的存儲(chǔ)、統(tǒng)一的元數(shù)據(jù)和權(quán)限、極致的查詢性能,以及AI + BI。
字節(jié)內(nèi)部的數(shù)據(jù)湖最初是基于開(kāi)源的數(shù)據(jù)湖框架Hudi構(gòu)建的,在嘗試規(guī)?;涞氐倪^(guò)程中,主要遇到了四個(gè)挑戰(zhàn):數(shù)據(jù)難管理、并發(fā)更新弱、更新性能差,以及日志難入湖。
如何應(yīng)對(duì)這些挑戰(zhàn)?字節(jié)做了問(wèn)題背后的詳細(xì)的原因分析,以及針對(duì)不同問(wèn)題,采取了不同的應(yīng)對(duì)策略。
1. 構(gòu)建一層統(tǒng)一的元數(shù)據(jù)層
為了解決數(shù)據(jù)難管理的問(wèn)題,字節(jié)在數(shù)據(jù)湖和數(shù)倉(cāng)之上,構(gòu)建了一層統(tǒng)一的元數(shù)據(jù)層,這層元數(shù)據(jù)層屏蔽了下層各個(gè)系統(tǒng)的元數(shù)據(jù)的異構(gòu)性,由統(tǒng)一的元數(shù)據(jù)層去對(duì)接 BI 工具,對(duì)接計(jì)算引擎,以及數(shù)據(jù)開(kāi)發(fā)、治理和權(quán)限管控的一系列數(shù)據(jù)工具。
2.使用樂(lè)觀鎖重新實(shí)現(xiàn)并發(fā)的更新能力
多任務(wù)的并發(fā)寫入是字節(jié)內(nèi)部實(shí)踐當(dāng)中一個(gè)非常通用的訴求。因此字節(jié)在Hudi Metastore Server的Timeline之上,使用樂(lè)觀鎖去重新實(shí)現(xiàn)了這個(gè)并發(fā)的更新能力。同時(shí),字節(jié)的并發(fā)控制模塊還能支持更靈活的行列級(jí)別并發(fā)寫策略,為實(shí)時(shí)數(shù)據(jù)關(guān)聯(lián)的場(chǎng)景的落地提供了一個(gè)可能。
與此同時(shí),在進(jìn)行高QPS入湖的情況下,字節(jié)遇到了單個(gè)Flink任務(wù)的擴(kuò)展性問(wèn)題和批流并發(fā)沖突的問(wèn)題。如何解決?
- 通過(guò)在Flink的 embedding term server上支持對(duì)當(dāng)前進(jìn)行中的事務(wù)元信息進(jìn)行緩存,大幅提升單個(gè)任務(wù)能夠并發(fā)寫入的文件量級(jí)。
- 提供更靈活的沖突檢查和數(shù)據(jù)合并策略——行級(jí)并發(fā)、列級(jí)并發(fā)和沖突合并。
3.采用可擴(kuò)展數(shù)據(jù)結(jié)構(gòu)hash
在早期的落地過(guò)程當(dāng)中,字節(jié)盡可能地復(fù)用Hudi的一些原生能力,比如Boom Filter index。但Bloom Filter存在假陽(yáng)性,規(guī)模達(dá)到一定量級(jí)之后,大部分?jǐn)?shù)據(jù)都是更新操作,沒(méi)有辦法再被索引加速。
Bloom Filter索引的問(wèn)題,根因是讀取歷史數(shù)據(jù)進(jìn)行定位,導(dǎo)致定位的時(shí)間越來(lái)越長(zhǎng)。對(duì)此,字節(jié)采用可擴(kuò)展數(shù)據(jù)結(jié)構(gòu)hash,無(wú)需讀歷史數(shù)據(jù),也可以快速定位到數(shù)據(jù)所在位置。
利用這個(gè)數(shù)據(jù)結(jié)構(gòu)結(jié)構(gòu),可以很自然地做桶的分裂和合并,讓整個(gè)bucket的索引從手動(dòng)駕駛進(jìn)化到自動(dòng)駕駛。在數(shù)據(jù)寫入的時(shí)候,也可以快速地根據(jù)現(xiàn)有的總數(shù),推斷出最深的有效哈希值的長(zhǎng)度,通過(guò)不斷地對(duì) 2 的桶深度次方進(jìn)行取余的方式,匹配到最接近的分桶寫入。
?
4.提供無(wú)索引的機(jī)制
日志難入湖的本質(zhì)原因在于Hudi的索引系統(tǒng),這個(gè)索引系統(tǒng)要求數(shù)據(jù)按照組件聚集,會(huì)帶來(lái)性能上的問(wèn)題以及資源上的浪費(fèi)。
無(wú)索引,即繞過(guò)Hudi的索引機(jī)制,做到數(shù)據(jù)的實(shí)時(shí)入湖。同時(shí)因?yàn)闆](méi)有主鍵,Upsert 的能力也失效了。字節(jié)在這方面提供了用更通用的 update 能力,通過(guò)shuffle hash join和 broadcast join 去完成數(shù)據(jù)實(shí)時(shí)更新。
02 阿里基于Flink Hudi的增量ETL架構(gòu)
過(guò)去半年,阿里巴巴計(jì)算平臺(tái)事業(yè)部 SQL 引擎組一直在開(kāi)發(fā)Apache Flink sql 模塊,核心工作是 Flink 與 Hudi 的集成。
為什么選擇Hudi而不是Iceberg或Dalta Lake?
這與Hudi的兩個(gè)能力有關(guān)系,一個(gè)是事務(wù)管理能力,另一個(gè)是upsert 能力。Hudi 提供的事務(wù)模型是快照級(jí)別,初步實(shí)現(xiàn)了海量數(shù)據(jù) upsert 以及事務(wù)的管理能力。
1.Hudi如何做到近實(shí)時(shí)的數(shù)據(jù)庫(kù)入湖?
最近興起的流批一體的架構(gòu),像debezium、canal 通過(guò)訂閱 MySQL binlog 事件的方式將增量數(shù)據(jù)近實(shí)時(shí)地導(dǎo)入數(shù)倉(cāng)之中,這就要求下游數(shù)據(jù)庫(kù)本身有 upsert 語(yǔ)義,而 Hudi 提供了這樣的能力,并且是目前做得比較成熟的,因此 Hudi 可以使用這兩種途徑至少在 ODS 層進(jìn)行近實(shí)時(shí)的數(shù)據(jù)庫(kù)數(shù)據(jù)入湖:
先使用debezium 采集 binlog,在使用 flink cdc connector 直接對(duì)接,flink cdc connector 具有 snapshot 再加增量消費(fèi)的能力,可以直接向下游擁有 upsert 的數(shù)據(jù)湖(如hudi)進(jìn)行同步,不需要再去接一層 kafka 就可以做到分鐘級(jí)別的入倉(cāng)入湖。
2.阿里如何構(gòu)建分鐘級(jí)別近實(shí)時(shí)的增量數(shù)倉(cāng)模型?
用傳統(tǒng)的方式構(gòu)建經(jīng)典的數(shù)倉(cāng)模型,需要通過(guò)調(diào)度系統(tǒng)按照某種時(shí)間策略構(gòu)建一個(gè)定期的 pipeline 任務(wù),依據(jù) pipeline 之間的依賴關(guān)系規(guī)定觸發(fā)機(jī)制,整體維護(hù)十分復(fù)雜。
Hudi 因?yàn)榫哂?upsert 的能力,因此可以利用 debezium 等工具,通過(guò) flink CDC 加 kafka 將數(shù)據(jù)庫(kù)數(shù)據(jù)近實(shí)時(shí)地同步到 ODS 層。如果Hudi 可以繼續(xù)將上游數(shù)據(jù)的變更數(shù)據(jù)流傳到下游,借助 flink CDC 的能力下游可以繼續(xù)消費(fèi)這種增量數(shù)據(jù),然后在原有狀態(tài)的基礎(chǔ)上繼續(xù)做增量計(jì)算。因此,阿里通過(guò)對(duì) hudi table format 進(jìn)行改動(dòng),構(gòu)建了分鐘級(jí)別近實(shí)時(shí)的增量數(shù)倉(cāng)模型。