天天看點

首次揭秘雲原生Hologres存儲引擎一、背景介紹二、資料模型三、存儲引擎架構四. Hologres存儲引擎技術亮點五. 結語

概要:剛剛結束的2020天貓雙11中,MaxCompute互動式分析(Hologres)+實時計算Flink搭建的雲原生實時數倉首次在核心資料場景落地,為大資料平台創下一項新紀錄。借此之際,我們将陸續推出雲原生實時數倉雙11實戰系列内容。本文将會首次對外公開介紹Hologres的存儲引擎,深度剖析其實作原理和核心技術優勢。

一、背景介紹

MaxCompute 互動式分析(Hologres)是阿裡雲自研開發的HSAP(Hybrid Serving/Analytical Processing)服務/分析一體化系統 ,融合了實時服務和分析大資料的場景,全面相容PostgreSQL協定并與大資料生态無縫打通。它的出現簡化了業務的架構,與此同時為業務提供實時做出決策的能力,讓大資料發揮出更大的商業價值。關于架構更詳細的介紹,請看文末VLDB論文 。

跟傳統的大資料和OLAP系統相比,HSAP系統面臨下面的挑戰:

  • 高并發的混合工作負載:HSAP系統需要面對遠遠超出傳統的OLAP系統的并發查詢。在實踐中,資料服務的并發遠遠超出OLAP的查詢。比如說,我們在現實的應用中見到資料服務需要處理高達每秒鐘數千萬個查詢,這比OLAP查詢的并發高出了5個數量級。同時,和OLAP查詢相比,資料服務型查詢對延遲有着更加苛刻的要求。複雜的混合查詢負載對系統的延遲和吞吐有着非常不同的取舍。如何在高效地利用系統的資源同時處理好這些非常不一樣的查詢,并且保證每個查詢的SLO是個巨大的挑戰。
  • 高吞吐實時資料導入:在處理高并發的查詢負載的同時,HSAP系統還需要處理海量的實時資料導入。從傳統的OLTP同步過來的資料隻是這其中的一小部分,其他還有大量的資料來自日志等沒有強事務語意的系統。實時導入的資料量遠遠超過了傳統的HTAP或者OLAP系統。和傳統的OLAP系統的另外一個差別是對資料的實時性有着很高的要求,導入的資料需要在秒級甚至亞秒級可見,這樣才能保證我們服務和分析結果的時效性。
  • 彈性和可擴充性:資料導入和查詢負載可能會有突發的高峰,這對HSAP系統提出了很高的彈性和可擴充性的要求。在現實的應用中,我們注意到資料導入峰值能達到是平均的2.5倍,查詢的峰值可能達到平均的3倍。資料導入和查詢的峰值可能不一定同時出現,這也需要系統有根據不同的峰值做迅速調整的能力。

基于上訴背景,我們自研了一款存儲引擎(Storage Engine),主要負責管理和處理資料, 包括建立,查詢,更新,和删除(簡稱 CRUD)資料的方法。存儲引擎的設計和實作提供了HSAP場景所需要的高吞吐,高并發,低延遲,彈性化,可擴充性的能力。根據阿裡集團業務和雲上客戶的需求,我們不斷創新和打磨,發展到今天,能支援單表PB級存儲,并完美支撐2020年天貓雙11核心場景千億個級别的點查詢和千萬個級别的實時複雜查詢 。

下面,我們将會對Hologres底層的存儲引擎做詳細的介紹,并介紹存儲引擎落地Hologres的具體實作原理和技術亮點。

二、資料模型

Hologres存儲引擎的基本抽象是分布式的表,為了讓系統可擴充,我們需要把表切分為分片(Shard)。 為了更高效地支援JOIN以及多表更新等場景,使用者可能需要把幾個相關的表存放在一起,為此Hologres引入了表組(Table Group)的概念。分片政策完全一樣的一組表就構成了一個表組,同一個表組的所有表有同樣數量的分片。使用者可以通過“shard_count"來指定表的分片數,通過“distribution_key"來指定分片列。目前我們隻支援Hash的分片方式。

表的資料存儲格式分為兩類,一類是行存表,一類是列存表,格式可以通過“orientation"來指定。

每張表裡的記錄都有一定的存儲順序,使用者可以通過“clustering_key"來指定。如果沒有指定排序列,存儲引擎會按照插入的順序自動排序。選擇合适的排序列能夠大大優化一些查詢的性能。

表還可以支援多種索引,目前我們支援了字典索引和位圖索引。使用者可以通過“dictionary_encoding_columns"和“bitmap_columns"來指定需要索引的列。

下面是一個示例:

首次揭秘雲原生Hologres存儲引擎一、背景介紹二、資料模型三、存儲引擎架構四. Hologres存儲引擎技術亮點五. 結語

這個例子建了LINEITEM 和 ORDERS兩個表,由于LINEITEM表還指定了主鍵(PRIMARY KEY),存儲引擎會自動建立索引來保證主鍵的唯一。使用者通過指定“colocate_with“把這兩個表放到了同一個表組。這個表組被分成24個分片(由shard_count指定)。 LINEITEM将根據L_ORDERKEY的資料值來分片,而ORDERS将根據O_ORDERKEY的資料值來分片。LINEITEM的L_SHIPINSTRUCT以及ORDERS的O_ORDERSTATUS字段将會建立字典。LINEITEM的L_ORDERKEY, L_LINENUMBER, L_SHIPINSTRUCT字段以及ORDERS的O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS字段将會建立位圖索引。

三、存儲引擎架構

1)總體架構

首次揭秘雲原生Hologres存儲引擎一、背景介紹二、資料模型三、存儲引擎架構四. Hologres存儲引擎技術亮點五. 結語

每個分片(Table Group Shard, 簡稱Shard)構成了一個存儲管理和恢複的單元 (Recovery Unit)。上圖顯示了一個分片的基本架構。一個分片由多個tablet組成,這些tablet會共享一個日志(Write-Ahead Log,WAL)。存儲引擎用了Log-Structured Merge (LSM)的技術,所有的新資料都是以append-only的形式插入的。 資料先寫到tablet所在的記憶體表 (MemTable),積累到一定規模後寫入到檔案中。當一個資料檔案關閉後,裡面的内容就不會變了。新的資料以及後續的更新都會寫到新的檔案。 與傳統資料庫的B+-tree資料結構相比,LSM減少了随機IO,大幅的提高了寫的性能。

當寫操作不斷進來,每個tablet裡會積累出很多檔案。當一個tablet裡小檔案積累到一定數量時,存儲引擎會在背景把小檔案合并起來 (Compaction),這樣系統就不需要同時打開很多檔案,能減少使用系統資源,更重要的是合并後, 檔案減少了,提高了讀的性能。

在DML的功能上,存儲引擎提供了單條或者批量的建立,查詢,更新,和删除(CRUD操作)通路方法的接口,查詢引擎可以通過這些接口通路存儲的資料。

2)存儲引擎元件

下面是存儲引擎幾個重要的的元件:

  • WAL 和 WAL Manager

WAL Manager是來管理日志檔案的。存儲引擎用預寫式日志(WAL) 來保證資料的原子性和持久性。當CUD操作發生時,存儲引擎先寫WAL,再寫到對應tablet的MemTable中,等到MemTable積累到一定的規模或者到了一定的時間,就會把這個MemTable切換為不可更改的flushing MemTable, 并新開一個 MemTable接收新的寫入請求。 而這個不可更改的flushing MemTable就可以刷磁盤,變成不可更改的檔案; 當不可更改的檔案生成後,資料就可以算持久化。 當系統發生錯誤崩潰後,系統重新開機時會去WAL讀日志,恢複還沒有持久化的資料。 隻有當一個日志檔案對應的資料都持久化後,WAL Manager才會把這個日志檔案删除。

  • 檔案存儲

每個tablet會把資料存在一組檔案中,這些檔案是存在DFS裡 (阿裡巴巴盤古或者Apache HDFS )。 行存檔案的存儲方式是Sorted String Table(SST) 格式。 列存檔案支援兩種存儲格式: 一種是類似PAX的自研格式, 另外一種是改進版的Apache ORC格式 (在AliORC的基礎上針對Hologres的場景做了很多優化)。 這兩種列存格式都針對檔案掃描的場景做了優化。

  • Block Cache (Read Cache)

為了避免每次讀資料都用IO到檔案中取,存儲引擎通過BlockCache把常用和最近用的資料放在記憶體中,減少不必要的IO,加快讀的性能。在同一個節點内,所有的Shard共享一個Block Cache。 Block Cache有兩種淘汰政策: LRU (Least Recently Used,最近最少使用) 和 LFU (Least Frequently Used, 最近不常用)。 顧名思義,LRU算法是首先淘汰最長時間未被使用的Block,而LFU是先淘汰一定時間内被通路次數最少的Block。

3)讀寫原理

Hologres支援兩種類型的寫入:單分片寫入和分布式批量寫入。兩種類型的寫入都是原子的(Atomic Write),即寫入或復原。單分片寫入一次更新一個Shard,但是需要支援極高的寫入頻率。另一方面,分布式批寫用于将大量資料作為單個事務寫到多個Shard中的場景,并且通常以低得多的頻率執行。

首次揭秘雲原生Hologres存儲引擎一、背景介紹二、資料模型三、存儲引擎架構四. Hologres存儲引擎技術亮點五. 結語
  • 單分片寫入

    如上圖所示,WAL管理器在接收到單分片寫請求後,(1)為寫請求配置設定一條Log Sequence Number (LSN),這個LSN是由時間戳和遞增的序号組成,并且(2)建立一條新的日志,并在檔案系統中的持久化這條日志。這條日志包含了恢複寫操作所需的資訊。在完全保留這條日志後,才向tablet送出寫入。之後,(3)我們會在相應tablet的記憶體表(MemTable) 中執行這個寫操作,并使其對新的讀請求可見。值得注意的是,不同tablet上的更新可以并行化。當一個MemTable滿了以後,(4)将其重新整理到檔案系統中,并初始化一個新的MemTable。最後,(5)将多個分片檔案在背景異步合并(Compaction)。在合并或MemTable重新整理結束時,管理tablet的中繼資料檔案将相應更新。

  • 分布式批量寫入

    接收到寫入請求的前台節點會将寫請求分發到所有相關的分片。這些分片通過兩階段送出機制(Two Phase Commit) 來保證分布式批量寫入的寫入原子性。

  • 多版本讀

    Hologres支援在tablet中多版本讀取資料。讀請求的一緻性是read-your-writes,即用戶端始終能看到自己最新送出的寫操作。每個讀取請求都包含一個讀取時間戳,用于構造讀的snapshot LSN。如果有一行資料的LSN大于snapshot LSN的記錄, 這行資料就會被過濾掉, 因為他是在讀的snapshot産生後才被插入到這個tablet的。

四. Hologres存儲引擎技術亮點

1)存儲計算分離

存儲引擎采取存儲計算分離的架構,所有的資料檔案存在一個分布式檔案系統(DFS, 例如阿裡巴巴盤古或者Apache HDFS)的裡面。當查詢負載變大需要更多的計算資源的時候可以單獨擴充計算資源; 當資料量快速增長的時候可以快速單獨擴充存儲資源。計算節點和存儲節點可以獨立擴充的架構保證了不需要等待資料的拷貝或者移動就能快速擴充資源; 而且,可以利用DFS存多副本的機制保證資料的高可用性。 這種架構不但極大地簡化了運維,而且為系統的穩定性提供了很大的保障。

2)異步執行流程

存儲引擎采用了基于事件觸發, 非阻塞的純異步執行架構, 這樣能夠充分發揮現代CPU多core的處理能力,提高了吞吐量, 支援高并發的寫入和查詢。這種架構得益于HOS(HoloOS) 架構,HOS在提供高效的異步執行和并發能力的同時,還能自動地做CPU的負載均衡提升系統的使用率。

3)統一的存儲

在HSAP場景下,有兩類查詢模式,一類是簡單的點查詢(資料服務Serving類場景),另一類是掃描大量資料的複雜查詢(分析Analytical類場景)。 當然,也有很多查詢是介于兩者之間的。這兩種查詢模式對資料存儲提出了不同的要求。行存能夠比較高效地支援點查詢,而列存在支援大量掃描的查詢上有明顯的優勢。

為了能夠支援各種查詢模式,統一的實時存儲是非常重要的。存儲引擎支援行存和列存的存儲格式。根據使用者的需求,一個tablet可以是行存的存儲格式 (适用于Serving的場景); 也可以是列存的存儲格式(适用于Analytical的場景)。 比如,在一個典型HSAP的場景,很多使用者會把資料存在列存的存儲格式下,便于大規模掃描做分析;與此同時,資料的索引存在行存的存儲格式下,便于點查。并通過定義primary key constraint (我們是用行存來實作的)用來防止資料重複·。不管底層用的是行存還是列存,讀寫的接口是一樣的,使用者沒有感覺,隻在建表的時候指定即可。

4)讀寫隔離

存儲引擎采用了snapshot read的語意,讀資料時采用讀開始時的資料狀态,不需要資料鎖,讀操作不會被寫操作block住; 當有新的寫操作進來的時候,因為寫操作是append-only,所有寫操作也不會被讀操作block住。這樣可以很好的支援HSAP的高并發混合工作負載場景。

5)豐富的索引

存儲引擎提供了多種索引類型,用于提升查詢的效率。一個表可以支援clustered index 和 non-clustered index這兩類索引。一個表隻能有一個clustered index, 它包含表裡所有的列。一個表可以有多個non-clustered indices。在non-clustered indexes裡,除了排序用的non-clustered index key外,還有用來找到全行資料的Row Identifier (RID)。 如果clustered index存在, 而且是獨特的,clustered index key就是RID; 否則存儲引擎會産生一個獨特的RID。 為了提高查詢的效率,在non-clustered index中還可以有其他的列, 這樣在某些查詢時,掃一個索引就可以拿到所有的列的值了 (covering index)。

在資料檔案内部,存儲引擎支援了字典和位圖索引。字典可以用來提高處理字元串的效率和提高資料的壓縮比,位圖索引可以幫助高效地過濾掉不需要的記錄。

五. 結語

存儲引擎的設計思路和研發方向是為了更好的支援HSAP的場景,能高效的支援高吞吐的實時寫入和互動式查詢,而且對離線的批量寫入做了優化。在寫入量和存儲量每年都成倍的增長下,Hologres經受住了嚴苛的考驗,完美地度過了多個雙11。 “Hologres頂住了5.96億每秒的實時資料洪峰,單表存儲高達2.5PB。基于萬億級資料對外提供多元分析和服務,99.99%的查詢可以在80ms以内傳回結果”。這組資料充分顯示了存儲引擎的技術能力, 同時也印證了我們技術架構和實作的優勢。

當然,Hologres還是一個新産品,HSAP是個新理念, “今天的最好隻是明天的開始”, 我們還在不斷地精益求精,聆聽客戶的回報,今後會在穩定性,易用性,以及功能和性能上持續提升。

另,後續還會持續推出有關HSAP存儲引擎和其他核心系統的技術揭秘,敬請期待!

論文:《

Alibaba Hologres: A cloud-Native Service for Hybrid Serving/Analytical Processing

》。

作者:江淵,阿裡巴巴資深技術專家,在資料庫和大資料領域有多年豐富的經驗。