天天看點

這十年,關于表格存儲 Tablestore 的演進曆程

作者:阿裡開發者
簡介: 表格存儲在 2009 年阿裡雲成立之初即立項研發,受 Google Bigtable 的啟發我們決定自研一個類似的分布式表存儲。在 2012 年 1 月表格存儲雲服務正式上線公測,是以到今年是作為雲服務上線滿 10 年。這篇文章接下來會先整體介紹下表格存儲 Tablestore,之後會分享下在技術層面産品這幾年的功能演進、技術架構演進以及穩定性優化相關的工作,以及在業務層面我們定義的核心應用場景和一些典型案例。

前言

表格存儲在 2009 年阿裡雲成立之初即立項研發,受 Google Bigtable 的啟發我們決定自研一個類似的分布式表存儲。由于是基于飛天核心開發,是以架構設計上我們選擇基于飛天平台提供高可擴充的分布式架構,基于盤古提供高可靠的資料存儲,最重要的是會基于雲來提供服務。在 2010 年釋出了第一個版本,服務的第一個客戶是雲郵箱,支撐其海量郵件中繼資料存儲。緊随 2011 年中阿裡雲官網的正式上線,在半年後的 2012 年 1 月表格存儲雲服務也正式上線公測。是以到今年已經算是表格存儲 Tablestore(簡稱為 OTS)誕生的第 13 個年頭,也是作為雲服務上線滿 10 年。

作為雲服務發展的這十年,産品功能在不斷完善,業務規模也在不斷增長。到目前為止,Tablestore 已經在全球 24 個地域的公共雲上輸出,服務數千企業客戶。我們也服務了集團内的衆多重要 BU,包括釘釘、菜鳥、淘特、天貓、高德、盒馬、螞蟻、優酷、飛豬等。在雲智能内部也是作為衆多雲服務的底層核心存儲,包括雲監控、MaxCompute、函數計算、智能存儲、視訊雲等。目前我們服務的叢集總規模超過數萬台,存儲資料量數百 PB。

阿裡集團内的業務對産品是一個很好的錘煉,因為在這裡有更複雜的場景、有更大的資料規模以及有對成本和性能更高的要求。我們也是在陪業務磨煉的這幾年,錘煉了我們核心,演進了我們在某些垂直場景下的差異化功能。業務規模變大,穩定性挑戰也變大,這十年也經曆過幾次重大故障。在存儲團隊内部穩定性一直是被定義為最高優先級的事,是以我們不斷優化架構來提升可用性。

這篇文章接下來會先整體介紹下表格存儲 Tablestore,之後會分享下在技術層面産品這幾年的功能演進、技術架構演進以及穩定性優化相關的工作,以及在業務層面我們定義的核心應用場景和一些典型案例。

産品介紹和發展曆程

功能大圖

這十年,關于表格存儲 Tablestore 的演進曆程

以一張資料流視圖的功能大圖來介紹下産品,Tablestore 所提供的基礎能力是分布式表存儲,這個表存儲有以下幾個特點:

  • 提供分區表模型,支援存儲規模的水準擴充:資料模型參考 Bigtable 的定義,這個模型目前在開源界被歸類為 WideColumn。簡單了解就是一個大寬表,這個表能存儲幾乎不限行數的資料記錄,每行資料會有一個行主鍵來辨別唯一性。在實體分布上,表會按照行主鍵的範圍來切分為不同的分區,通過分布式的排程這些分區來提供可擴充的能力。
  • 提供 Serverless 服務形态,更簡單使用:在使用上隻需要開通服務就可以直接使用,無需購買 ECS 執行個體來部署服務。使用者看到的隻有資料存儲和請求,底層的實體資源不可見,底層配置設定的實體資源随着表的存儲規模和通路量變化自動彈性伸縮。
  • 靈活的資料索引,加速資料的查詢和檢索:Bigtable 定義的表存儲模型隻有對行主鍵的索引,是以能提供非常快速的單行查詢和主鍵範圍查詢。但是在實際的業務需求中,使用者還需要基于非主鍵列進行條件查詢,或者是需要支援更複雜的例如多字段組合查詢或者是全文檢索等實時查詢和檢索。是以我們在後續的功能演進中在 Bigtable 模型上進行了擴充,能夠支援對表資料自動建構索引,并且提供多類索引結構(二級索引和多元索引,後文會介紹),針對不同的查詢模式進行優化。
  • 便捷的資料管理,管理資料生命周期和資料流轉:随着資料規模的變大,資料管理會越難。Tablestore 提供更便捷的資料管理功能,包括支援 TTL 自動淘汰過期資料、支援資料的自動冷熱分層來降低成本,以及通過通道服務(Tunnel Service)實作表資料的分布式 CDC(變更資料捕獲) 能力讓資料能實時流轉。
  • 完善的企業級特性,更安全的使用:Tablestore 是長在雲上的,是以整個資源管理、網絡和賬号體系都是基于雲的基礎服務來建構。支援基于 RAM 的賬号授權,支援基于 SLR 的服務間通路授權、支援 VPC 等專有網絡以及支援基于 KMS 的 BYOK 透明加密。

場景示意

這十年,關于表格存儲 Tablestore 的演進曆程

我們看一個真實的例子來了解 Tablestore 的這些功能是怎麼組合使用的,以物聯網裝置狀态資料存儲場景為例。在這個場景下需要存儲數億裝置的狀态資料,且每個裝置會定期彙報其最新狀态資料。這個場景下的表結構設計非常簡單,表中每一行對應存儲一個裝置的資料。在 Tablestore 内隻需要建立這麼一張表,就能滿足這個場景下的基礎功能,滿足數億裝置的狀态更新、查詢和存儲的需求,且能随着裝置規模的變大自動水準擴充。此時如果這個場景下需要實作更進階的功能:

  • 需要實作根據多個裝置狀态屬性做組合條件檢索:隻需要通過 API 對表建立一個多元索引,即可滿足表内任意字段的多條件組合檢索。
  • 需要捕獲裝置的最新狀态變更做一些實時計算:隻需要通過 API 對表建立一個分布式 CDC 通道,即可對接 Flink 進行實時計算。
  • 需要定時分析所有裝置狀态産出統計報表:隻需要在 MaxCompute/Spark 内通過 SQL 建立一個外表關聯,即可使用 MaxCompute/Spark 的計算引擎對表内資料進行全量分析。

Data Serving

Tablestore 提供結構化資料存儲服務,在應用資料這塊結構化資料存儲最常使用的是關系資料庫,是以我們也經常會被問到與關系資料庫的差別是什麼。從資料應用角度來回答這個問題,關系資料庫定位在 Transaction Process,而 Tablestore 定位在 Data Serving。Transaction Process 是一個基于資料 Full State 的資料處理,任何資料變更都需要保證資料狀态的完整性和一緻性。而 Data Serving 更強調保障資料的 online service,保證在任意規模下提供高可靠、高可用的資料服務。

Transaction Process 和 Data Serving 實際是上下遊的關系,通常在應用系統中資料的産生是一個 Transaction Process 的過程,而資料生成後需要提供的是 Data Serving 服務。舉個實際的應用場景,在電商系統中每筆訂單的生成是一個 Transaction Process 的過程,因為需要關聯商品、價格、庫存、賬戶等狀态資料才能确定是否能産生訂單,需要基于一個完整資料實體的 Full State 來做事務處理。而訂單生成後則會轉換為提供 Data Serving,此時的資料應用場景主要是查詢和簡單的資料更新。

發展曆程

這十年,關于表格存儲 Tablestore 的演進曆程

在 Tablestore 發展的十餘年内,在功能演進層面我們主要分為三個階段:

  • 1.0 階段(提供穩定的表存儲服務):Tablestore 的核心基礎能力是提供 Serverless 表存儲服務,作為雲服務上線後前 5 年都是在持續打磨表引擎、穩定性以及 Serverless 産品化能力。
  • 2.0 階段(更完善的資料服務能力):滿足基本的存儲服務需求後,客戶對資料服務能力提出了一系列更高的要求:希望支援索引,提供更靈活的資料查詢和檢索;希望能支援資料實時流轉,進行實時計算或實時 ETL 至數倉;希望能直接通過開源計算引擎進行資料分析。是以我們在 17 年開始規劃一系列重大功能特性,在 19 年的時候釋出了我們的 2.0 版本,釋出了通道服務(分布式 CDC)、資料索引(二級索引和多元索引)以及與計算生态的對接(MaxCompute/Spark/Flink/DLA等)。
  • 3.0 階段(安全、成本、性能、使用者體驗):滿足基本的資料服務需求後,客戶對安全、成本、性能和使用者體驗提出了更高的要求。我們釋出了統一查詢 SQL 來簡化 API 調用,對接 HBR 支援資料備份、支援 BYOK 資料加密,更新了最新版表引擎核心讓性能有大幅提升。3.0 階段整體還未完成,部分功能還在不斷打磨。

在形态演進層面,從一開始我們就定位為基于雲提供 Serverless 的服務,随着業務的發展這個形态有所延伸。在 15 年随着專有雲輸出線下,我們進入了郵政、氣象、國網、國稅、醫保、公安等項目。專有雲有其特殊的服務形态,有與公共雲不同的服務模式,是産品能力另一個角度的延伸。在 16 年我們開始海外輸出,支援阿裡雲業務全球部署。

技術架構和核心元件

整體架構

這十年,關于表格存儲 Tablestore 的演進曆程
  • 存儲層:底層依賴盤古和 OSS,線上會部署全閃和混閃盤古叢集對應目前提供的高性能和容量型兩類存儲規格。對于要求低成本存儲低頻通路的冷資料,我們會使用 OSS 來存儲。
  • 引擎層:目前有兩個資料引擎,分别是表引擎和索引引擎。索引引擎的資料是實時同步自表引擎,對表内的資料實時建構索引。兩個資料引擎間的資料同步使用 CDC 引擎,CDC 引擎能實時捕獲表内的資料更新,并提供訂閱的能力。
  • 服務層
    • 資料接口:應用通路 Tablestore 服務的統一入口,所有功能都是通過 API 對外提供。這一層的能力除了對底層管控和資料接口的封裝外,還管理使用者認證、權限、流控等等。
    • 統一查詢:使用 SQL 作為查詢引擎,底層對接表引擎和索引引擎。

Tablestore 會複用大量存儲内部的基礎技術,包括誇父、女娲、飛天基礎庫等。這些基礎技術在存儲其他産品線不斷磨煉,我們能直接享受到能力提升帶來的技術紅利。Tablestore 自研最核心的部分是引擎層和服務層,接下來會分别介紹下這些重要元件。

分布式表引擎

這十年,關于表格存儲 Tablestore 的演進曆程

表引擎是 Tablestore 的核心,資料索引、更新訂閱和資料管理都是圍繞表引擎建構,是以其必須具備很強的性能、很高的擴充性以及穩定性。總結下表引擎的核心技術:

  • 存算分離架構:底層依賴盤古分布式檔案系統,提供高可靠的資料存儲。存算分離帶來的優勢是計算和存儲可靈活擴充,分别具備靈活度很強的彈性能力,是提供 Serverless 服務的基礎。
  • 動态分區,自動負載均衡:分區是表具備分布式能力的基礎,動态分區是表具備彈性擴充能力的基礎。表的動态分區能力支援分區的自動分裂,且分裂期間将分區的不可用時間優化到百毫秒内,對使用者請求幾乎無影響。通過自動負載均衡靈活排程分區,自動探測并消除通路熱點,保證資源均衡減少通路抖動。
  • 高性能資料引擎:表引擎内部使用了大量技術來優化讀寫性能,包括使用者态通信架構(Luna)、線程切換和記憶體拷貝優化、無鎖資料結構、行列混存資料塊優化等等,對比同類開源引擎有數倍的性能提升。
  • 高可用,穩定性優化:影響可用性的場景主要包括突發流量、負載不均衡以及 Worker 節點的 Failover。我們通過全局流控和單機流控結合來處理突發流量,利用動态負載均衡來均衡資源和消除通路熱點,優化 Worker 節點的 Failover 時間降低影響,目前單叢集的可用性已經能達到 99.99%。另外曆年的故障和越來越複雜環境下的線上問題也讓我們看到并解決了很多 corner case 問題,對穩定性提升也有很大的幫助。

分布式 CDC 引擎

通道服務是 Tablestore 提供的 CDC 能力,CDC 的全稱是 Change Data Capture,提供實時捕獲表内資料更新的能力。有很多資料庫産品都提供類似能力,比如 MySQL Binlog、DynamoDB Stream 以及 CosmosDB Change Feed 等。可以說 CDC 是現代資料系統中核心資料元件必備的能力之一,因為它有幾個非常關鍵的用途:

  • 異構存儲實時同步:現代應用架構中包含很多異構存儲元件,例如資料庫、緩存、搜尋引擎、消息隊列等,資料會在這些元件間實時流轉。如何保證這些異構元件間的資料一緻性是一個技術難點,一個比較好的架構實踐是選取唯一的 DataSource,作為整個系統中資料的『Single source of truth』,通過捕獲這個 DataSource 的變化來實作實時同步。
  • 事件驅動架構:事件驅動是一個很好的解耦應用系統的最佳架構實踐,很多包含多種微服務的複雜應用系統應用了事件驅動技術,例如不同服務間通過消息隊列來實時異步的傳遞消息進而能實作完全的解耦。應用與應用間通過消息隊列來實作事件驅動,而資料存儲與應用間需要通過 CDC 技術來實作事件驅動。
  • 實時計算:在很多應用場景中需要對資料進行實時統計,例如雙十一大屏。計算實時性依賴于資料的流轉速度,存儲與實時計算的對接需要依賴 CDC 技術來提升流轉速度。
這十年,關于表格存儲 Tablestore 的演進曆程

上圖是 Tablestore 通道服務的架構,表由多個分區構成,每個分區會包含一個 Commit Log 隊列,隊列内按照資料寫入順序儲存了該分區内的所有資料更新記錄。如果發生分區分裂,老分區的隊列會停止寫入,分裂出來的兩個新分區會寫入各自的新的隊列。通道服務本質上開放了分區内 Log 隊列的資料查詢,但是僅僅開放查詢接口還不夠,通道服務内實作了以下幾個關鍵技術:

  • 全增量一體:異構存儲間需要資料實時同步并且保持資料最終一緻,則需要先同步目前全量資料後在同步增量。Log 隊列内不會儲存全量資料,隻儲存最近一段時間内的資料,是以如果要同步全量則需要直接讀表。通道服務底層封裝了全量和增量資料的查詢,對外暴露一緻的接口,大大簡化了使用。
  • 分布式保序消費:保證資料一緻的關鍵是能夠嚴格按照資料變更記錄順序進行回放,如果僅查詢一個隊列,保序是比較好實作的。但是由于分區會動态分裂産生新的分區,是以會導緻同一行資料的變更記錄可能會存在不同的隊列中。老分區和新分區間形成父子關系,要實作保序就得保證先消費父分區再消費子分區。在通道服務内部管理了分區間的父子關系,并且能夠嚴格保證父子分區的消費順序。
  • 消費狀态管理:通道服務管理了資料生産端以及能夠保證消費行為的正确性(例如保序消費),但是由于消費端是托管在客戶應用内,是以很難管理消費端的運作情況。如果消費端出現異常,會導緻資料消費滞後。為此通道服務在服務端提供消費狀态管理,消費端會實時上報狀态和消費統計。利用此狀态資料,可以快速定位消費滞後的異常節點。

分布式索引引擎

主表提供基礎的主鍵索引,僅能提供簡單的根據主鍵查詢或者是主鍵範圍查詢。但是很多場景下,需要根據非主鍵列做條件查詢,此時需要建構索引來加速。索引可以是内置也可以外置,也可以使用内外組合的方案。例如 MySQL 提供聯合索引能滿足絕大部分場景下的查詢加速,這是純内置的方案。但是聯合索引使用上會有局限,要求查詢條件必須符合索引列的最左比對原則,是以在查詢條件需要靈活組合的場景不得不選擇用 Elasticsearch 作為外置索引。

這就是一個典型的内外組合的場景,使用是非常常見的。内置索引的好處是能夠比較簡單管理表與索引的一緻性,也能更好的保證明時同步。外置索引雖然靈活,但是在處理資料一緻性、以及優化資料同步延遲上有非常大的挑戰。早期在 Tablestore 沒有提供内置索引時,使用者大多數選擇的是外置索引的方案,遇到了同樣的問題。是以我們決定研發我們的内置索引,并且同時提供類 MySQL 的聯合索引和類 Elasticsearch 的反向索引,滿足絕大部分場景的需求。

Tablestore 提供的類 MySQL 聯合索引的能力叫二級索引,提供分區内強一緻的 LocalIndex 以及全局最終一緻的 GlobalIndex。二級索引的資料分布和索引結構與主鍵索引的實作是一緻的,邏輯上看二級索引就是另外一張表,該表是對主表資料的另一個次元的重新排序。二級索引的功能由表引擎直接提供,這一章節主要介紹另一個類 Elasticsearch 能力的多元索引的架構。

這十年,關于表格存儲 Tablestore 的演進曆程

上圖是多元索引的架構,總結下多元索引的核心技術:

  • 存算分離架構:底層也是依賴盤古分布式檔案系統,多元索引所需要動态調配的計算資源會更多,是以更需要依賴存算分離技術。
  • 可擴充的查詢能力:多元索引的資料分區能提供多個讀副本,這是與表引擎的資料分區很不一樣的地方,因為多元索引主要為查詢做優化。讀副本支援動态擴充,當探測到查詢負載過高時系統能夠自動擴充讀副本,依賴于共享存儲架構能夠在秒級别完成。
  • 資料組織優化:
    • 哈希分區:由于多元索引提供的是不确定的多字段條件組合查詢,是以很多場景下無法篩選結果資料所在分區,通常都是一個全分區的聯合查詢,内部采取 scatter-gather 的執行模式。為避免有分區查詢長尾,是以分區間盡量資料均衡,是以多元索引的資料分區采取的是 Hash Partition 的政策,差別于表的 Range 政策。
    • 路由鍵:某些場景下查詢條件中會帶固定的條件字段,例如訂單索引表的查詢通常是會給定 userid 條件,如果能根據固定條件提前做分區篩選,那查詢效率能更高。是以我們提供了 Routing Key 的政策,與 Hash Partition 組合使用,如果查詢條件中給定了 routing key 的值,則能提前做分區篩選。
    • 預排序:如果資料排序與查詢結果順序一緻,則可以無需查詢出所有結果後進行全排序,隻需要擷取到滿足條數的結果即可直接傳回,對查詢效率是一個很大的提升。是以多元索引提供了預排序的能力,如果查詢條件總是按某個順序傳回結果,則可以定義預排序來進行優化。
  • 多類型索引結構:索引結構有多種,例如 B-tree、Hash、Bitmap、BKD-tree、Reverted Index 等,每種索引結構針對特定的查詢模式優化。針對我們常見的查詢場景,多元索引實作了優化數值範圍查詢的 BKD-tree 索引以及優化多條件組合檢索的 Reverted Index。
  • 自适應優化和索引重建:上面提到的資料組織優化中路由鍵和預排序政策都是需要根據實際的查詢模式來決定的,很多業務在一開始設計索引時無法提前考慮到所有的優化政策。是以多元索引提供了自适應的優化,會自動分析常見的查詢模式來決定是否采取路由鍵和預排序優化措施,并且自動重建索引,對上層使用是完全透明的。
  • 動态索引列和灰階切換政策:很多應用場景在上線後會有新增索引列的需求,多元索引提供了兩種添加索引列的方式。如果需要存量資料重建索引,我們提供了灰階切換政策,新索引會在背景重建索引,索引資料追平後可以進行查詢流量灰階,如果沒問題可以操作切換或者回切,保證新索引能安全上線。如果不需要對存量資料進行索引重建,則新增索引列可以僅對新資料生效。

統一查詢引擎

最早 Tablestore 僅提供 API 的通路方式,每個 API 對應底層每個基礎子產品的原子功能。純 API 的好處是使用者能比較靈活的組合調用底層功能,具備很強的 DIY 能力,但是不便之處有很多:

  • 應用層代碼邏輯極其複雜:一個簡單的單行查詢用 SQL 來表達的話主體邏輯隻需要一行代碼,但是裸調 API 的形式至少需要數倍代碼量。如果是調用多元索引的統計聚合,複雜的 Group By 加多層聚合代碼量甚至能達到幾十倍。
  • 在查詢時無法附帶一些簡單的資料處理:通常從存儲層查詢出結果資料後,某些場景下不需要傳回原始結果,而是需要一些統計聚合結果,例如 Sum 和 Avg 等。裸 API 無法表達計算處理,有了 SQL 後就能很容易支援一些輕量級的統計聚合。
  • 很難高效的自主選擇索引和反查主表:索引選擇依賴一些 RBO 或 CBO 優化算法,應用層勉強可以自己實作幾個簡單的 RBO,但是很難進行 CBO 優化。另外索引選擇優化算法最好是服務内內建,這樣不需要每個應用單獨實作一套。另外如果要查詢索引後反查主表,需要分别調用索引的查詢 API 後再調用主表的 API,實作起來非常複雜。
  • 無法提供互動式的查詢:代碼裸調 API 很難實作互動式的查詢邏輯,通常需要使用 SQL 來支援。
  • 應用組合 MySQL 使用或從 MySQL 遷移過來,需要很大的改造代價:很多場景是把 Tablestore 作為 MySQL 的分層存儲曆史資料,由于表結構是大體相同的,是以查詢邏輯也是大體相同的。如果不支援 SQL,應用層需要很大的查詢代碼改造代價來适配 API。

上述都是來自真實的場景和客戶真實的回報,是以我們考慮良久在 Tablestore 3.0 的規劃中決定引入 SQL 查詢引擎。但是引入 SQL 前,在架構設計上我們要想清楚幾個關鍵點:

  • SQL 提供的是關系模型還是聯邦查詢?我們 SQL 的定位是做聯邦查詢而不是表達獨立的模型,主要有兩點:一是 Tablestore 的底層模型能表達更豐富的語義不完全與關系模型相容;二是底層多種資料模型間需要有資料聯合查詢的需求。
  • API 和 SQL 的關系是什麼?上面一個定位搞明白了,SQL 和 API 的關系也清楚了,SQL 會基于 API 來建構。或者更精确的說 API 定義底層資料模型抽象,SQL 基于此在上層再做一層抽象。
  • Data Serving 場景對算力的要求是什麼?具體到技術名額,我們希望提供高并發、高 QPS 和低延遲的查詢,要求不同 SQL 執行引擎架構選擇和優化目标也會不同。
  • SQL 引擎優化目标是什麼?基于上面的目标,在 Data Serving 場景我們主要優化的目标是:一是提供可水準擴充的 SQL 執行引擎;二是優化機關算力下的性能,而不是如何排程更多算力。
這十年,關于表格存儲 Tablestore 的演進曆程

以上就是 SQL 引擎的架構,它的核心技術點包括:

  • 提供聯邦查詢能力:基于底層存儲引擎提供的 API 來建構,實作 API 寫入的資料能被 SQL 查詢。
  • 自适應索引選擇和主表反查:根據 RBO 和 CBO 優化索引選擇,支援自動反查主表。
  • 可水準擴充的執行引擎:與 API 層類似架構,采用無狀态對等節點,可水準擴充支援更高 QPS。
  • 機關算力下的性能優化:做了一系列優化來優化機關算力下的計算性能,包括:1. 與存儲層的資料交換協定優化;2. 更多計算下推到存儲層執行;3. 計算引擎的輸入資料采取列編碼,以應用向量化執行技術來優化性能。

核心應用場景

這一章節會給大家介紹下 Tablestore 的幾個核心的應用場景,我們對『核心』場景的定義是:

  1. 在該場景下 Tablestore 在核心能力方面具備一定的競争力,例如成本、性能和規模等。
  2. 有已有的大規模、成熟、高要求業務穩定運作多年,并經過大流量的考驗。
  3. 在該場景下 Tablestore 具備一定的差異化特性,對應用架構帶來很大的收益。

點選檢視原文,擷取更多福利!

https://developer.aliyun.com/article/1132651?utm_content=g_1000368280

版權聲明:本文内容由阿裡雲實名注冊使用者自發貢獻,版權歸原作者所有,阿裡雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿裡雲開發者社群使用者服務協定》和《阿裡雲開發者社群知識産權保護指引》。如果您發現本社群中有涉嫌抄襲的内容,填寫侵權投訴表單進行舉報,一經查實,本社群将立刻删除涉嫌侵權内容。

繼續閱讀