博客 / 詳情

返回

Meta公司內部項目-RaptorX:將Presto性能提升10倍

概要速覽

RaptorX是Meta(前“Facebook公司”,下文統稱“Meta”)公司的一個內部項目名稱,目的是為了降低查詢延遲,讓Presto的查詢性能大大超越原生(vanilla) Presto,這篇文章介紹了RaptorX的關鍵模塊——分層緩存。

有了分層緩存,我們能夠將查詢性能提升10倍。這一新的架構不僅可以完勝像Raptor之類以性能為導向的連接器,還具有向存儲分離化(即存算分離架構)進行持續拓展和支持的額外優勢。

存儲分離化存在的問題

存儲分離化是行業朝着獨立存算擴容發展的必然趨勢,能夠幫助雲服務供應商降低成本。Presto本身支持這樣的存算分離架構,而數據可以從部署了Presto的服務器之外的遠程存儲節點獲取。

儘管如此,存算分離對查詢延遲提出了新的挑戰,因為在網絡飽和的情況下,通過網絡掃描海量數據會受到IO的限制。此外,元數據訪問和操作路徑也需要通過網絡來獲取數據的位置;幾個元數據RPC來回就能輕易地把延遲抬高到一秒以上,下圖用橙線表示Hive連接器的IO相關操作路徑,每條路徑都可能成為查詢性能的瓶頸。

圖片

RaptorX:搭建分層緩存解決方案

過去,為了解決網絡飽和的問題,Presto通過內嵌的Raptor連接器,將數據從遠端存儲加載到本地的SSD(固態硬盤),從而實現快速訪問,然而,這種解決方案與計算/存儲共享節點差別不大,有悖於存算分離的理念。該解決方案的缺點很明顯:要麼因為worker節點的SSD空間已滿而浪費CPU,要麼因為CPU受限而浪費SSD容量。於是,Meta啓動了RaptorX項目的開發。

RaptorX是為了將Presto查詢性能提升至少10倍而開展的一個內部項目,其中分層緩存是RaptorX項目成功的關鍵。當存儲節點與計算節點分離時,緩存的作用尤為顯著。開發RaptorX的目的不是為了推出一個新的連接器或產品,而是構造一套內嵌的解決方案,讓現有的工作負載無需遷移即可直接從中獲益,該解決方案目前主要針對許多工作負載常用的Hive連接器。

下圖展示了緩存解決方案的整體架構,該緩存具有分層結構,本文會詳細介紹:

圖片

* Metastore版本化的緩存方案:我們把表/分區信息緩存到coordinator中,鑑於元數據是可變的,就像Iceberg或Delta Lake那樣,因此信息是被版本化的,我們只與metastore同步版本信息,並僅在當前版本失效時去獲取最新版本。
* 文件列表緩存:將來自遠端存儲分區目錄的文件列表緩存起來。
* 片段結果緩存:在leaf worker的本地SSD上緩存部分計算結果。由於查詢會不斷變化,所以我們需要運用裁剪技術來簡化查詢計劃。
* 文件句柄(file handle)和footer的緩存:在leaf worker內存中緩存打開的文件描述符(file descriptor)和stripe/文件footer信息,因為在讀取文件時這些數據往往會被頻繁訪問。
* Alluxio數據緩存:在leaf worker的本地SSD上用對齊的1MB大小數據塊來緩存文件段。該庫(library)是通過Alluxio的緩存服務搭建的。
* 親和調度器:是指根據文件路徑固定地向對應worker發送請求,從而使緩存命中率最大化的調度器(scheduler)。

Metastore版本化的緩存

Presto coordinator會緩存表的元數據(模式、分區列表和分區信息),以避免向Hive Metastore發起耗時很長的getPartitions調用,但是,Hive表的元數據是可變的,所以我們需要進行版本管理並確定已緩存的元數據是否有效,因此,coordinator為每個緩存的鍵值對賦予了一個版本號。當收到讀取請求時,coordinator會查詢Hive Metastore,獲取(未被緩存的)分區信息,或者與Hive Metastore核對確認已經緩存的信息是否是最新的。雖然和Hive Metastore進行遠程交互的操作不可避免,但與獲取全部分區信息相比,版本匹配的成本相對較低。

文件列表緩存

Presto coordinator將文件列表緩存在內存中,從而避免對遠端存儲發起耗時很長的listFile調用。這隻適用於封閉的目錄, 而對於開放分區,為了確保數據的實時性,Presto不會緩存這些目錄。開放分區的一個主要用例是支持近實時的數據導入和處理。在這種情況下,數據導入引擎(如微批數據micro batch)將不斷向開放分區寫入新的文件,以便Presto可以讀取近實時的數據。其他諸如壓縮、metastore更新或為近實時導入數據創建副本等詳細信息不在本文的討論範圍內。

片段結果緩存

運行在leaf 階段的Presto worker可以決定將部分計算結果緩存在本地SSD上,這麼做是為了防止多次查詢時進行重複計算。最典型的用例是將執行計劃的包括掃描、過濾、投影和/或聚合的片段結果緩存在leaf階段 。

例如,假設一個用户發送了以下查詢,其中ds是一個分區列:

SELECT SUM(col) FROM T WHERE ds BETWEEN'2021-01-01' AND '2021-01-03'

對2021-01-01、2021-01-02和2021-01-03每個分區(更準確地説是相應的文件)計算的部分求和結果將被緩存在leaf worker上,形成一個“片段結果”,現在假設用户發送了另外一項查詢:

SELECT sum(col) FROM T WHERE ds BETWEEN '2021-01-01'AND '2021-01-05'

現在,Leaf worker便可以直接從緩存中獲取2021-01-01、2021-01-02和2021-01-03的片段結果(部分求和結果),並且只需要對2021-01-04和2021-01-05兩個分區計算部分求和即可。

由於片段結果是基於leaf查詢片段的,用户可以添加或刪除過濾器或投影,因此非常靈活。上述例子表明,只包含分區列的過濾器很容易處理。但是為避免由於頻繁變化的非分區列過濾器造成的緩存失效,我們引入了基於分區統計信息的裁剪策略,請看下述查詢,其中time是一個非分區列:

SELECT SUM(col) FROM T
WHERE ds BETWEEN '2021-01-01'AND'2021-01-05'
ANDtime > now() - INTERVAL'3' DAY

請注意:now()函數的值始終在變,如果leaf worker根據now()的絕對值來緩存計劃片段,幾乎不可能會命中緩存,但是,如果predicate(謂詞條件) time > now() - INTERVAL '3' DAY是對於大多數分區來説為真(true)的“寬鬆”條件,我們可以在調度時把該謂詞從計劃中刪除。

例如,如果今天是2021-01-04,那麼我們知道對於分區ds = 2021-01-04,predicate time > now() - INTERVAL '3' DAY總是成立的。

如下圖所示,一般而言,它包含一個謂詞條件和3個分區 (A, B, C),以及各分區同謂詞條件相關的最小值(min)、最大值(max)的統計信息(stats)。當分區統計域與謂詞域沒有任何重疊時(如分區A),我們可以直接裁剪掉該分區,不需要向worker發送分片(split)。如果分區統計域完全包含在謂詞域中(如分區C),那麼我們不需要該謂詞,因為它對這個特定的分區總是成立的,我們可以在進行計劃對比時省略該謂詞條件。對於其他與謂詞有一些重疊的分區,我們仍需要用給定的過濾器掃描整個分區。

圖片

文件描述符和footer緩存

Presto worker將文件描述符緩存在內存中,避免對遠端存儲進行耗時較長的openFile調用。此外,worker還會把經常訪問到的列文件和stripe footer緩存在內存中。目前支持的文件格式是ORC,DWRF和Parquet。在內存中緩存此類信息的原因是footer作為針對數據建立的索引信息通常具有高緩存命中率。

Alluxio 數據緩存

Alluxio數據緩存是一個主要特性區別於被淘汰的Raptor連接器。Presto worker每次進行讀取操作時將遠端存儲數據以它原始格式(經過壓縮或者可能也經過加密)緩存在本地SSD上。對於將來的讀取請求,如果讀取範圍內的數據已經緩存在本地SSD上,則該讀取請求將直接從本地SSD返回結果。緩存庫是我們與Alluxio和Presto開源社區共同搭建的。

緩存機制將每次讀取對齊成1MB固定大小的數據塊,這裏的1MB是可以根據不同的存儲能力進行配置的。比如,假設Presto發起一次從偏移量0開始的長度為3MB的讀取請求,那麼Alluxio緩存會檢查0-1MB、1-2MB和2-3MB的數據塊是否已經緩存在磁盤上,然後只遠程獲取尚未被緩存的數據塊。緩存清除策略基於LRU,會從磁盤上刪除最久沒被訪問過的數據塊。Alluxio數據緩存為Hive連接器提供了標準的Hadoop文件系統接口,並且基於專門用來支撐規模達到Meta級別工作負載的高性能、高併發且可容錯的存儲引擎,以透明的方式對請求的數據塊進行緩存。

圖片

軟親和調度

為了最大程度地提高worker的緩存命中率,coordinator需要將同一文件的請求調度給同一個worker。因為文件的一部分很有可能已經被緩存在那個特定的worker上了。調度策略是“軟”的,也就是説,如果目標worker太忙或不可用,調度器會退而求其次,安排給它的備選worker進行緩存,或者在必要時直接跳過不予緩存。該調度策略確保了緩存不在關鍵路徑上,但仍然能夠提升性能。

Performance性能

Meta已經在公司內部全面部署了RaptorX緩存並進行了實戰測試。為了與原生(vanilla) Presto進行性能比較,我們在一個包含114個節點的集羣上進行了TPC-H基準測試。每個worker都有1TB的本地SSD,每個任務配置4個線程。我們在遠端存儲中準備了放大係數(scale factor)為100的TPC-H表。下圖展示了Presto和裝備了分層緩存的Presto之間的性能對比結果。

圖片

從基準測試結果來看,像Q1、Q6、Q12-Q16、Q19和Q22這樣的重掃描或重聚合的查詢都能實現超過10倍的延遲改善。甚至像Q2、Q5、Q10或Q17這樣的重關聯查詢也有3-5倍的延遲改善。

User Guide用户指南

要完全啓用該功能,我們需要為worker配備本地的SSD,為了能夠啓用本文所述的各個緩存層,請進行以下配置:

調度(/catalog/hive.properties):

hive.node-selection-strategy=SOFT_AFFINITY

Metastore版本化的緩存(/catalog/hive.properties):

hive.partition-versioning-enabled=true
hive.metastore-cache-scope=PARTITION
hive.metastore-cache-ttl=2d
hive.metastore-refresh-interval=3d
hive.metastore-cache-maximum-size=10000000

文件列表緩存(/catalog/hive.properties):

hive.file-status-cache-expire-time=24h
hive.file-status-cache-size=100000000
hive.file-status-cache-tables=*

數據緩存(/catalog/hive.properties):

cache.enabled=true
cache.base-directory=file:///mnt/flash/data
cache.type=ALLUXIO
cache.alluxio.max-cache-size=1600GB

片段結果緩存(/config.properties and /catalog/hive.properties):

fragment-result-cache.enabled=true
fragment-result-cache.max-cached-entries=1000000
fragment-result-cache.base-directory=file:///mnt/flash/fragment
fragment-result-cache.cache-ttl=24h
hive.partition-statistics-based-optimization-enabled=true

文件和stripe footer 緩存(/catalog/hive.properties):

● 針對ORC 或DWRF格式:hive.orc.file-tail-cache-enabled=true

hive.orc.file-tail-cache-size=100MB
hive.orc.file-tail-cache-ttl-since-last-access=6h
hive.orc.stripe-metadata-cache-enabled=true
hive.orc.stripe-footer-cache-size=100MB
hive.orc.stripe-footer-cache-ttl-since-last-access=6h
hive.orc.stripe-stream-cache-size=300MB
hive.orc.stripe-stream-cache-ttl-since-last-access=6h

針對Parquet格式:

hive.parquet.metadata-cache-enabled=true
hive.parquet.metadata-cache-size=100MB
hive.parquet.metadata-cache-ttl-since-last-access=6h

文章貢獻者:

Meta:Abhinav Sharma, Amit Dutta, Baldeep Hira, Biswapesh Chattopadhyay, James Sun, Jialiang Tan, Ke Wang, Lin Liu, Naveen Cherukuri, Nikhil Collooru, Peter Na, Prashant Nema, Rohit Jain, Saksham Sachdev, Sergey Pershin, Shixuan Fan, Varun Gajjala
Alluxio: Bin Fan, Calvin Jia, HaoYuan Li
Twitter: Zhenxiao Luo
Pinterest: Lu Niu
引用
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.