從數磚開源 Delta Lake 說起

作者:鄭鍇,花名鐵傑,阿里巴巴高級技術專家,Apache Hadoop PMC,Apache Kerby 創立者。深耕分佈式系統開發和開源大數據多年,先後專注在安全,存儲和計算領域。之前在 Intel,目前轉戰阿里雲上,致力於提供更好用更有彈性的 Hadoop/Spark 大數據平臺。


Spark AI 北美峯會的第一天,坊間傳聞被證實,Databrics(俗稱數磚,亦稱磚廠)的殺手鐗 Delta 產品特性作爲 Delta Lake 項目開源!會前,筆者有幸同磚廠的兩位大佬李瀟和連城做了個線下交流,談到 Delta 時被告知會有相關重磅在大會上宣佈,但卻沒想到是開源出去。爲什麼呢?Delta 作爲 Databrics Runtime 下一代引擎被高調發布兩年不到吧,按說油水滾滾地來,這麼快就放出去?不過想來也是,Spark 社區最近兩年總體感覺提振乏力,潛在的競爭對手 Flink 則在阿里和一衆國內大廠的紛紛加持下風生水起,Spark 可能不得不防。Delta 本質上解決了大數據分析場景中常見的數據更新的問題,從開源大數據這個生態圈子來看,Hive 早已經做掉了 ACID 事務支持;Uber 發起了 Hoodi,Netflix 搞 Iceberg,雙雙進入 Apache 孵化器,解決類似問題。再等下去顯然對 Spark 和社區發展不太有利,感覺數磚不僅對 Spark 把控得好,對商業和開源節奏的把握也很到位。Delta Lake 開源這個事情可謂引爆全場,筆者爲了這篇文章多點乾貨要去相關 session 聽一聽的,結果面對浩浩蕩蕩的排隊,只好作罷。文章爲了蹭熱點趕得有點急,細節上多有謬誤的話,還望拍磚指正。

商業之類的不好說,我們還是言歸正傳談技術。Delta Lake 是什麼?簡單來說就是支持 delta 的 Data Lake(數據湖),可以說是 Data Lake 2.0 吧。之前的數據湖只支持批量插入,寫入失敗容易產生髒數據,導致查詢分析失敗;現在支持事務更新,允許一邊讀一邊更新,甚至多個 writer 同時操作,ACID 的那種,保證一致性地讀取和分析查詢。最新的操作修改能查詢得到嗎?在大會第一天的 Expo Theater 上,Renold Xin 回答我的問題時特意強調,只要 commit 掉的 edits,當下的查詢就可見。解決了這類問題可不得了,這可以說是近年來開源大數據的一個重要發展,意味着從粗放到精細,從野蠻到文明;在此之前具有類似意義的有 Parquet/ORC 這種列式存儲格式的引入,和 Arrow 這種數據集內存表示格式的支持。種種跡象表明,大數據發展到現在必須精耕細作,這也對大數據平臺研發的從業者有了更高的要求。Delta 涉及諸多特性包含很多亮點,最核心的是什麼呢?我們來嘗試探究其背後的技術本質和發展脈絡,從 delta 的字面意思來看,其核心關注點在於數據更新操作和由此產生的增量數據寫入。不是大數據背景的可能就問了,更新操作有什麼大不了,計算機系統不就是幹這個事情的嗎?更新就更新唄,直接修改掉,怎麼出來個增量數據?回答這些問題之前我們先扯遠一點。Spark 對全量數據利用 SparkSQL 做批處理已經十分成熟,對實時流數據利用 Spark Structured Streaming 做實時計算本身也沒有太大問題,現在都在講批流一體,Spark 基於 RDD 的 micro-batch 老早就進行了批流統一,在性能延時和吞吐之間取得了很好的平衡,在大多數情況下都是沒有問題的。不管是批處理還是流處理,背後的大數據存儲考慮的都是一寫多讀,講究吞吐量,寫主要是追加寫,寫新的數據分區,或者在往已有的分區裏面追加數據,總而言之不支持隨機修改。你要想做隨機修改的話,那就自己做,比如 HBase,簡單來講就是把修改記錄攢起來,攢夠了閾值再寫出去。因此在實時數倉場景裏面,實時處理的時候做表的更新(插入,刪除,修改),麻煩可就來了,因爲表背後的數據通常按只讀的 Parquet/ORC 格式存儲,沒辦法修改。怎麼辦,更新操作記錄到單獨的文件裏面,記 edit log 吧,Delta 裏面叫 transaction log,叫啥反正就是所謂 delta 數據。增量數據 delta 就是這樣來的,當然是相對於全量數據或者基線數據也就是 base 數據而言。這裏面有些重要問題,一個是這個過程會產生大量的 delta 小文件,需要及時做合併;處理場景可能本身還要求事務支持和多版本,滿足回溯或回滾;讀的話不能只讀原來那些 Parquet/ORC 文件了,還得考慮吸收這些 delta 文件。這種情況下存儲用強一致性的 HDFS 還好,用 S3 這種最終一致性的可就慘了,數磚幾乎 all in cloud,S3 是重頭戲,這也就能解釋數磚爲什麼會在 AI 高漲的時候搞出個 Delta 這麼大的動靜,搞出一種新的 table format 也就是 Delta Table 來系統性的應對這些挑戰,實在有點影響主旋律。Delta 的重要性毋庸置疑,藉助於 Delta,在數磚 all in 的存儲計算分離情景裏面,無論批處理,流處理,還是機器學習深度學習,全都能搞定,而且藉助於 DBIO 的緩存優化,data skipping 或者文件索引技術,性能還槓槓滴!

Delta 這類技術總結一下就是,按列式格式寫 base 數據加快分析讀,增量更新數據 delta 則採取行式寫入支持事務和多版本,然後系統通過後臺不斷地進行 delta 合併。這種方式將存儲格式和計算結合起來考慮,一方面支持傳統的海量數據分析查詢,另一方面也支持事務更新寫入,讀和寫採取不同的優化路徑,是一種非常成熟的存儲架構模式。這種模式越來越多地出現在 HTAP(Hybrid transaction/analytical processing,OLAP + OLTP)系統裏面。最近幾年 HTAP 有點熱,新出現的系統有點多,感覺大家都往這上面靠,八仙過海各有神通。比如開源大數據領域的 Hive,SparkSQL,原本只是批處理分析的,藉助於類似 Delta 這種方案的加持,也就沾上了邊。國內這兩年比較活躍的 TiDB,微軟的 SQL Server,原本是 OLTP 爲主,也都想辦法配備上了 Spark,支持分析負載。開源大數據領域比較早的算是 Cloudera 的 Kudu + Impala 組合,前些年經常看到他們的演示,一邊做些記錄更新,一邊 Impala 查詢馬上就能得到最新結果,當時的 Hive 和 Spark 此情此景是不是很慚愧不得而知。更清奇的是消息訂閱分發系統,竟也能裝扮一新搖身變成 HTAP,像 Kafka 很明顯在往這個方向走,Apache Pulsa 也是。前不久有幸跟 StreamNative 的創始人 Sijie 聊到細節,Pulsa 的做法挺有意思,跟 Kafka 不一樣的是,對於流入 Pulsa 系統的事件消息,Pulsa 都掖着藏着自己管着,不用額外的 ETL 過程轉走了,對於較早的消息則通過內置服務來轉儲爲 Parquet 這種列式文件,然後利用現有的計算引擎比如 Spark,Hive 或 Presto 做分析;對應分析 job 同時作爲一個消息的消費者來拉取最新流入的消息,從而達到批流統一,滿足實時性。Kudu 的做法有些類似,不過實現上更緊湊,記錄是直接以行式寫到內存上的 B 樹,然後再異步刷到磁盤;後臺再對這些增量數據進行合併,寫列式存儲文件。這個時候如果啓動 Impala 查詢,就會高效讀取到這些列式存儲文件,但是對於還沒有合併的行式增量更新文件,則只有全部讀進來自己合併得到完整結果。如果還在內存裏面呢?更甚者,如果還在分佈式一致性寫入協議過程中呢,也就是說還沒有 committed?我懷疑類似 Pulsa 和 Kudu 的這類系統可能會處理不好,畢竟分析引擎和過程是另外的,跟存儲系統分開了,總不能侵入式讀取寫入節點的內存吧。因此從本質上來講,這類系統因爲分析時可能讀取不到最新更新操作,可能並不算是最嚴格意義上的 HTAP。不過在開源大數據領域,在原有的海量數據分析上面支持更新操作,能夠按照版本或者時間支持 snapshot isolation 一致性地讀,已經是個很大的進步了,畢竟主要還是解決大數據場景問題。與此相對應,螞蟻的 OceanBase 號稱是金融級別的,已經有大量 case 用於銀行金融業務,因爲是一個從存儲到查詢都高度一體化的系統,從理論和工程上來講可以做到分析統計更實時更精確。類似於 SQL Server,OceanBase 首先是一個 OLTP 數據庫,因此無論是查詢還是更新操作,無論是點查還是範圍查詢,都要求很高性能,因此在存儲設計上跟上述大數據背景的系統有很大區別,不過也還是遵循了 Delta 背後的類似工程思路,就是讀和寫走不同的優化路徑,數據分爲基線存儲和內存事務增量存儲,增量存儲最終合併進入基線存儲。具體的區別在於,基線存儲採取行式而非列式,做法上跟 HBase 有不少類似,單位存儲塊內的行集排好序,並支持創建 bloom filter 等索引,有利於點查和範圍查詢。內存事務寫入上,delta 數據記錄爲一個操作鏈,並做好 B+ 樹和哈希索引,同樣爲了快速點查和範圍查詢。這些裝置當然主要是對 OLTP 事務操作和查詢來準備的,OLAP 類的報表統計查詢應該同樣可以利用。有意思的是,OceanBase 的存儲塊比較小,十分有利於做合併,大多數塊在合併過程中可以保持不變,即使合併需要重新生成塊涉及的數據量也不大。大數據存儲系統動則幾十上百兆的塊,比如 HDFS 默認 128MB,很難想象僅僅爲了合併寫入幾條更新記錄,重寫這麼大的數據塊。扯了這麼遠,回到數磚即將開源的 Delta 上來,它是如何實現高效合併的?我在會上專門問過 Renold,回答說是可以參數控制,不過還是有點不太清楚,搞明白的同學麻煩分享一下,我也想知道。筆者所在的團隊正在做類似的事情,因爲是一個全新的存儲系統,在一開始我們就把 Delta 考慮進來,單位存儲塊不大也不小,在合併更新寫入上和吞吐上走了一個平衡。對這方面工作感興趣的同學可以加好友交流,也歡迎加入我們,一起共創未來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章