背景:2020年9月16日,Snowflake成功IPO,交易首日市場估值達到704億美元,募集資金34億美元。Snowflake成為迄今為止規模最大的軟體IPO,市值最高突破1200億美元。Snowflake提供基于雲的資料存儲和分析服務,一般被稱為 "資料倉庫即服務",它允許企業使用者使用基于雲的硬體和軟體來存儲和分析資料。Snowflake自2014年起在亞馬遜S3上運作,自2018年起在微軟Azure上運作,自2019年起在谷歌雲平台上運作,其Snowflake Data Exchange允許客戶發現、交換和安全地共享資料。[維基百科]
Snowflake取得了巨大的商業成功,技術是如何支撐起它的千億美元市值呢?它技術強在哪?OLAP核心技術愛好者浙川為大家傾情解讀Snowflake的核心技術原理。本文為該系列二。
Snowflake中的雲原生技術
本章節将圍繞資料存儲、虛拟倉庫和雲服務元件,來詳細展開介紹Snowflake設計中的技術細節,分析他們是如何充分利用底層雲服務的架構和資源的。
資料存儲
Snowflake的資料存儲元件是建構在Amazone S3存儲服務之上的,之是以采用這樣的設計選擇,是因為Amazon S3存儲服務提供了高易用性、高服務可靠性,以及嚴格的資料持久性保證。S3的這些特性大大降低了Snowflake進行資料存儲開發的成本,Snowflake的資料存儲設計隻需要考慮本地緩存、資料傾斜修複等特性即可。
然而,和直接使用本地存儲比起來,S3卻存在一些限制。S3具有更高的資料通路延遲,同時每個S3的I/O請求需要更高的CPU開銷,尤其是使用HTTPS連接配接的情況下。另外,S3是對象存儲,其資料存儲操作接口就是PUT/GET/DELETE等簡單接口,資料對象隻能作為整體被寫入,不支援帶有偏移量的寫入(但支援帶有偏移量的讀取),也不支援資料追加寫(append)。
S3的這些特點影響着Snowflake在資料表檔案格式上的設計選擇。Snowflake将其資料庫橫向分區為多個大檔案,每個檔案就類似于傳統資料庫存儲系統中的資料塊或者資料頁概念,檔案一旦生成,就不再改變。每個檔案中,表資料以列存格式進行存儲,每一列資料在實體上存放到一起,然後再進行壓縮。每個檔案都對應一個檔案頭,檔案頭包括基本存儲中繼資料資訊,例如每一列資料在檔案中的偏移。由于S3是支援帶有偏移量的資料讀取的,是以,隻需要将檔案頭資料拿到,就可以根據需要通路某一列的資料了。
Snowflake還會利用S3存儲複雜查詢(例如大規模join)計算過程中産生的臨時資料,這樣可以支援系統運作任意複雜類型的查詢,而不會導緻系統記憶體或本地存儲被耗盡。Snowflake還會将查詢結果存儲到S3中,以簡化使用者執行互動式查詢的系統複雜度,因為不需要再像傳統資料庫那樣針對互動式查詢維護一個cursor了。
資料庫級别的中繼資料資訊如表的中繼資料、表對應的S3檔案、統計資訊、事務資訊等,儲存在雲服務相關元件中的分布式key-value存儲中。
虛拟倉庫
虛拟倉庫實質上是由EC2執行個體組成的叢集,組成虛拟倉庫的每個獨立的EC2執行個體又稱為計算節點。Snowflake的使用者不會直接和計算節點進行互動,他們甚至不需要關注由多少計算節點組成了他們的虛拟倉庫。使用者隻需要選擇虛拟倉庫的配置,而這些配置就像T恤衫的尺碼一樣,被抽象成X-Small到XX-large的範圍供使用者選擇。
彈性和隔離性。作為純粹、彈性的計算資源,虛拟倉庫可以在任意時間進行按需地建立、銷毀或者重新配置。建立或者銷毀虛拟倉庫不會影響資料倉庫中存儲的使用者資料,這樣設計的好處就是使用者可以根據他們的計算需求動态地申請計算資源,使用者甚至可以在沒有任何計算需求的情況下銷毀所有的資料倉庫,而不用關心他們資料存儲量的大小。
使用者的每個查詢請求會被配置設定到某個虛拟倉庫上進行執行。由于不同的虛拟倉庫并不會共享同一個計算節點,是以,不同虛拟倉庫上運作的查詢之間互相不會有資源競争和性能影響,即性能隔離性得到了很好的滿足。當然,虛拟倉庫不共享計算節點也有它的弊端,比如整個系統的資源使用率會很低,Snowflake後續會專門針對這一點做優化和提升。
虛拟倉庫在執行查詢請求的時候,每個計算節點上會對應生成一個計算程序,計算程序的生命周期就是這個查詢請求的生命周期。當計算程序遇到了錯誤,可以簡單通過重試來解決。是以,Snowflake在查詢層面具有較高的容錯性,但是Snowflake目前隻執行整個查詢的重試,并不支援重試查詢下的某個子任務。需要強調的是,查詢開始時建立計算程序、結束後銷毀計算程序這種模式适合執行時間比較長的分析型查詢,但對于執行時間很短的短查詢,建立、銷毀計算程序的開銷就太大了。為了對短查詢進行優化,Snowflake在一個由若幹個計算節點組成的集合中維護特定的計算程序,這些程序專門用來執行短查詢,短查詢執行結束後,這些程序并不會被銷毀,而是重複利用執行後續的短查詢。
在Snowflake中,使用者可以申請多個虛拟倉庫,每個虛拟倉庫上可以并發運作多個查詢。每個虛拟倉庫都共享相同的表資料,他們不需要為了運作計算任務而單獨地拷貝資料。這樣的設計方案有效地利用了彈性和隔離性的優點:Snowflake的使用者可以任意按需擴充虛拟倉庫的數量和配置,但是隻需要存儲和操作一份資料;不同負載的查詢任務可以運作在不同的虛拟倉庫上,虛拟倉庫之間的計算資源是互相獨立的,這樣可以保證不同負載的查詢之間互不影響性能。
根據Snowflake統計的實踐經驗,虛拟倉庫的彈性還可以為使用者帶來成本效益更高的服務:在幾乎同樣的價格下,使用者可以享受更快的性能。例如,如果某個工作負載在4個計算節點上執行需要花費15個小時,那麼在32個計算節點上執行可能隻需要花費2個小時。雖然這兩種模式的價格是差不多的,但是帶給使用者的體驗卻有着根本的差別:在同樣花費的情況下,性能越快使用者感受就會越好。而虛拟倉庫的彈性恰恰為使用者提供了極佳體驗的選擇,使用者可以配置虛拟倉庫,以更快地完成計算任務,但是并不需要額外多的花費開銷。
緩存和檔案轉移。虛拟倉庫中,每個計算節點會在本地對通路過的表資料進行緩存,緩存對象即為資料表在S3上對應的檔案。本地一定會進行緩存的資料是檔案頭(詳細内容參見5.3.1章節),根據檔案頭的資訊可以下載下傳任意指定要通路的資料計算節點上的緩存資料是可以被該節點上的查詢任務共享。當緩存容量達到上限時,Snowflake采取簡單的LRU(Least-Recently-Used)算法來進行緩存替換。
為了提高緩存命中率,同時為了避免在同一個虛拟倉庫中不同的計算節點上緩存相同的表資料檔案,Snowflake将不同的表檔案分布到不同的計算節點上,分布算法采用的是針對表名的一緻性hash算法。需要操作同一個表檔案的查詢請求都會通路同一個計算節點。同時,Snowflake采用的是惰性一緻性hash算法:即當計算節點的數目發生改變的時候,不會立即對計算節點上的檔案進行重新分布,而是當LRU算法需要對緩存的檔案進行替換的時候,再将新的檔案根據最新計算節點的數目進行一緻性hash分布。這樣設計的好處就是不會因為立即的資料重新分布而影響正在執行的查詢任務,相比于會立即進行大量資料重新分布的shared-nothing架構,具有更高的可用性和使用者體驗。
在實際運作中,Snowflake還會遇到傾斜(skew)問題:一些計算節點可能由于虛拟化、網絡競争、負載過高等問題,其響應速度遠遠低于其他計算節點,這就會導緻這些計算節點可能會拖慢需要通路它們緩存資料的其他查詢的性能。為了解決這樣的傾斜問題,Snowflake在檔案掃描階段做了額外的處理邏輯。當某個計算節點掃描完輸入檔案而需要從其他計算節點讀取資料檔案時,它會向目标節點發送檔案讀取請求。如果目标節點目前負載很高,它不會直接傳回檔案資料,而是回複将該檔案的使用權轉移給請求節點。發生檔案轉移後,請求節點在目前查詢的生命周期内,可以直接從S3上下載下傳資料檔案,而不需要再從目标節點那裡通路資料檔案。這樣就避免了在慢節點上再增加額外的負載,以減輕系統的傾斜情況。
執行引擎。保證系統的可擴充性十分重要,提升系統單節點的計算性能同樣十分重要:同樣的執行時間下,能用10台計算節點就肯定不用1000台計算節點。Snowflake針對其系統的執行引擎也做了大量優化,以提升其單計算節點上的計算性能,進而為使用者提供更好成本效益的服務。Snowflake的計算引擎采用了三大技術:列存、向量化、結果下推。
對于分析型場景來說,列式存儲的收益往往優于行式存儲的效率,因為在隻通路較少列的情況下,列式存儲的CPU使用率和I/O使用率會更高。同時,列式存儲可以更友善地應用SIMD指令集,也具有更高的資料壓縮率。
Snowflake采用的向量化執行方案源自于MonetDB/X100方案。Snowflake避免了中間結果的物化,而是以流水線的形式批量地處理資料(一次處理幾千行對應的列資料),這種方式不僅大大降低了I/O的開銷,而且有效地提升了cache的使用效率。
Snowflake的結果下推采用的是經典的火山模型:在Snowflake中,關系型算子可以将它們的結果直接下推給下遊的算子,而不是等着下遊的算子來這裡拉取結果。這種下推方式可以減少不必要的控制流邏輯,提升cache的使用效率。結果下推還讓Snowflake有能力處理DAG(Directed Acyclic Graph)執行計劃,DAG執行計劃可以對中間結果資料進行更高效的共享和流水線化。
很多傳統資料庫執行引擎所不得不面臨的設計開銷對Snowflake的執行引擎而言可能并不需要關注。比較典型的就是Snowflake在執行查詢請求的時候,并需要考慮事務管理相關的問題。如5.3.1章節所述,Snowflake的檔案一旦寫入到S3中,就不會再改變了,是以,Snowflake的查詢執行是建立在不可變檔案上的,是以事務管理是不需要的。同時,Snowflake也沒有維護記憶體緩沖區。在Snowflake中,大部分查詢操作的資料量都非常的大,如果采用記憶體緩沖區來緩存這麼大量的資料,雖然會提升查詢性能,但是代價也是非常大的:會消耗大量寶貴且昂貴的記憶體。相反,Snowflake會将複雜查詢(包括join、group by、sort等)的中間結果儲存到本地磁盤上,并遞歸地對磁盤資料進行操作。磁盤的容量遠遠高于記憶體,價格也相對便宜。基于這樣的設計,Snowflake幾乎可以處理任意負載類型的查詢任務,包括極其複雜的大規模join或者agg計算。
注:譯文來自
https://www.snowflake.com/resource/sigmod-2016-paper-snowflake-elastic-data-warehouse/[[Snowflake核心技術解讀系列一]架構設計](連結位址
https://developer.aliyun.com/article/780125?spm=a2c6h.13148508.0.0.e93f4f0etphv6M)随時歡迎技術圈的小夥伴們過來交流^_^:
AnalyticDB詳情見:
産品詳情AnalyticDB産品試用:
産品試用AnalyticDB知乎公衆号:
雲原生資料倉庫AnalyticDB開發者社群公衆号:
AnalyticDB開發者釘釘群:23128105
AnalyticDB相關文章:
AnalyticDB MySQL擁抱雲原生,強力支撐雙十一 智穩雙全--AnalyticDB如何助力菜鳥運配雙十一 千萬商家的智能決策引擎--AnalyticDB如何助力生意參謀雙十一 AliExpress智能營銷引擎大揭秘-AnalyticDB如何做到快準狠省 十萬億級OLAP引擎解讀-AnalyticDB如何支撐資料銀行超大規模低成本實時分析