雲原生數據庫設計新思路

本文做者爲 PingCAP 聯合創始人兼 CTO 黃東旭,將分享分佈式數據庫的發展趨勢以及雲原生數據庫設計的新思路。

在講新的思路以前,先爲過去沒有關注過數據庫技術的朋友們作一個簡單的歷史回顧,接下來會談談將來的數據庫領域,在雲原生數據庫設計方面的新趨勢和前沿思考。首先來看看一些主流數據庫的設計模式。數據庫

常見的分佈式數據庫流派

分佈式數據庫的發展歷程,我按照年代進行了分類,到目前爲止分紅了四代。第一代是基於簡單的分庫分表或者中間件來作 Data Sharding 和 水平擴展。第二代系統是以 Cassandra、HBase 或者 MongoDB 爲表明的 NoSQL 數據庫,通常多爲互聯網公司在使用,擁有很好的水平擴展能力。設計模式

第三代系統我我的認爲是以 Google Spanner 和 AWS Aurora 爲表明的新一代雲數據庫,他們的特色是融合了 SQL 和 NoSQL 的擴展能力,對業務層暴露了 SQL 的接口,在使用上能夠作到水平的擴展。緩存

第四代系統是以如今 TiDB 的設計爲例,開始進入到混合業務負載的時代,一套系統擁有既能作交易也能處理高併發事務的特性,同時又能結合一些數據倉庫或者分析型數據庫的能力,因此叫 HTAP,就是融合型的數據庫產品。性能優化

將來是什麼樣子,後面的分享我會介紹關於將來的一些展望。從整個時間線看,從 1970 年代發展到如今,database 也算是個古老的行業了,具體每一個階段的發展狀況,我就不過多展開。網絡

數據庫中間件

對於數據庫中間件來講,第一代系統是中間件的系統,基本上整個主流模式有兩種,一種是在業務層作手動的分庫分表,好比數據庫的使用者在業務層裏告訴你;北京的數據放在一個數據庫裏,而上海的數據放在另外一個數據庫或者寫到不一樣的表上,這種就是業務層手動的最簡單的分庫分表,相信你們操做過數據庫的朋友都很熟悉。數據結構

第二種經過一個數據庫中間件指定 Sharding 的規則。好比像用戶的城市、用戶的 ID、時間來作爲分片的規則,經過中間件來自動的分配,就不用業務層去作。架構

這種方式的優勢就是簡單。若是業務在特別簡單的狀況下,好比說寫入或者讀取基本能退化成在一個分片上完成,在應用層作充分適配之後,延遲仍是比較低的,而總體上,若是 workload 是隨機的,業務的 TPS 也能作到線性擴展。併發

可是缺點也比較明顯。對於一些比較複雜的業務,特別是一些跨分片的操做,好比說查詢或者寫入要保持跨分片之間的數據強一致性的時候就比較麻煩。另一個比較明顯的缺點是它對於大型集羣的運維是比較困難的,特別是去作一些相似的表結構變動之類的操做。想象一下若是有一百個分片,要去加一列或者刪一列,至關於要在一百臺機器上都執行操做,其實很麻煩。app

NoSQL - Not Only SQL

在 2010 年先後,好多互聯網公司都發現了這個大的痛點,仔細思考了業務後,他們發現業務很簡單,也不須要 SQL 特別複雜的功能,因而就發展出了一個流派就是 NoSQL 數據庫。NoSQL 的特色就是放棄到了高級的 SQL 能力,可是有得必有失,或者說放棄掉了東西總能換來一些東西,NoSQL 換來的是一個對業務透明的、強的水平擴展能力,但反過來就意味着你的業務原來是基於 SQL 去寫的話,可能會帶來比較大的改形成本,表明的系統有剛纔我說到的 MongoDB、Cassandra、HBase 等。less

最有名的系統就是 MongoDB,MongoDB 雖然也是分佈式,但仍然仍是像分庫分表的方案同樣,要選擇分片的 key,他的優勢你們都比較熟悉,就是沒有表結構信息,想寫什麼就寫什麼,對於文檔型的數據比較友好,但缺點也比較明顯,既然選擇了 Sharding Key,多是按照一個固定的規則在作分片,因此當有一些跨分片的聚合需求的時候會比較麻煩,第二是在跨分片的 ACID 事務上沒有很好的支持。

HBase 是 Hadoop 生態下的比較有名的分佈式 NoSQL 數據庫,它是構建在 HDFS 之上的一個 NoSQL 數據庫。Cassandra 是一個分佈式的 KV 數據庫,其特色是在 KV 操做上提供多種一致性模型,缺點與不少 NoSQL 的問題同樣,包括運維的複雜性, KV 的接口對於原有業務改造的要求等。

第三代分佈式數據庫 NewSQL

剛纔說過 Sharding 或者分庫分表,NoSQL 也好,都面臨着一個業務的侵入性問題,若是你的業務是重度依賴 SQL,那麼用這兩種方案都是很不溫馨的。因而一些技術比較前沿的公司就在思考,能不能結合傳統數據庫的優勢,好比 SQL 表達力,事務一致性等特性,可是又跟 NoSQL 時代好的特性,好比擴展性可以相結合發展出一種新的、可擴展的,可是用起來又像單機數據庫同樣方便的系統。在這個思路下就誕生出了兩個流派,一個是 Spanner,一個是 Aurora,兩個都是頂級的互聯網公司在面臨到這種問題時作出的一個選擇。

Shared Nothing 流派

Shared Nothing 這個流派是以 Google Spanner 爲表明,好處是在於能夠作到幾乎無限的水平擴展,整個系統沒有端點,無論是 1 個 T、10 個 T 或者 100 個 T,業務層基本上不用擔憂擴展能力。第二個好處是他的設計目標是提供強 SQL 的支持,不須要指定分片規則、分片策略,系統會自動的幫你作擴展。第三是支持像單機數據庫同樣的強一致的事務,能夠用來支持金融級別的業務。

表明產品就是 Spanner 與 TiDB,這類系統也有一些缺點,從本質上來講一個純分佈式數據庫,不少行爲沒有辦法跟單機行爲如出一轍。舉個例子,好比說延遲,單機數據庫在作交易事務的時候,可能在單機上就完成了,可是在分佈式數據庫上,若是要去實現一樣的一個語義,這個事務須要操做的行可能分佈在不一樣的機器上,須要涉及到屢次網絡的通訊和交互,響應速度和性能確定不如在單機上一次操做完成,因此在一些兼容性和行爲上與單機數據庫仍是有一些區別的。即便是這樣,對於不少業務來講,與分庫分表相比,分佈式數據庫仍是具有不少優點,好比在易用性方面仍是比分庫分表的侵入性小不少。

Shared Everything 流派

第二種流派就是 Shared Everything 流派,表明有 AWS Aurora、阿里雲的 PolarDB,不少數據庫都定義本身是 Cloud-Native Database,但我以爲這裏的 Cloud-Native 更可能是在於一般這些方案都是由公有云服務商來提供的,至於自己的技術是否是雲原生,並無一個統一的標準。從純技術的角度來去說一個核心的要點,這類系統的計算與存儲是完全分離的,計算節點與存儲節點跑在不一樣機器上,存儲至關於把一個 MySQL 跑在雲盤上的感受,我我的認爲相似 Aurora 或者 PolarDB 的這種架構並非一個純粹的分佈式架構。

原來 MySQL 的主從複製都走 Binlog,Aurora 做爲一種在雲上 Share Everything Database 的表明,Aurora 的設計思路是把整個 IO 的 flow 只經過 redo log 的形式來作複製,而不是經過整個 IO 鏈路打到最後 Binlog,再發到另一臺機器上,而後再 apply 這個 Binlog,因此 Aurora 的 IO 鏈路減小不少,這是一個很大的創新。

日誌複製的單位變小,意味着我發過去的只有 Physical log,不是 Binlog,也不是直接發語句過去,直接發物理的日誌能表明着更小的 IO 的路徑以及更小的網絡包,因此整個數據庫系統的吞吐效率會比傳統的 MySQL 的部署方案好不少。

Aurora 的優點是 100% 兼容 MySQL,業務兼容性好,業務基本上不用改就能夠用,並且對於一些互聯網的場景,對一致性要求不高的話,數據庫的讀也能夠作到水平擴展,無論是 Aurora 也好,PolarDB 也好,讀性能是有上限的。

Aurora 的短板你們也能看得出來,本質上這仍是一個單機數據庫,由於全部數據量都是存儲在一塊兒的,Aurora 的計算層其實就是一個 MySQL 實例,不關心底下這些數據的分佈,若是有大的寫入量或者有大的跨分片查詢的需求,若是要支持大數據量,仍是須要分庫分表,因此 Aurora 是一款更好的雲上單機數據庫。

第四代系統:分佈式 HTAP 數據庫

第四代系統就是新形態的 HTAP 數據庫,英文名稱是 Hybrid Transactional and Analytical Processing,經過名字也很好理解,既能夠作事務,又能夠在同一套系統裏面作實時分析。HTAP 數據庫的優點是能夠像 NoSQL 同樣具有無限水平擴展能力,像 NewSQL 同樣可以去作 SQL 的查詢與事務的支持,更重要的是在混合業務等複雜的場景下,OLAP 不會影響到 OLTP 業務,同時省去了在同一個系統裏面把數據搬來搬去的煩惱。目前,我看到在工業界基本只有 TiDB 4.0 加上 TiFlash 這個架構可以符合上述要求。

分佈式 HTAP 數據庫:TiDB (with TiFlash)

爲何 TiDB 可以實現 OLAP 和 OLTP 的完全隔離,互不影響?由於 TiDB 是計算和存儲分離的架構,底層的存儲是多副本機制,能夠把其中一些副本轉換成列式存儲的副本。OLAP 的請求能夠直接打到列式的副本上,也就是 TiFlash 的副原本提供高性能列式的分析服務,作到了同一份數據既能夠作實時的交易又作實時的分析,這是 TiDB 在架構層面的巨大創新和突破。

下圖是 TiDB 的測試結果,與 MemSQL 進行了對比,根據用戶場景構造了一種 workload,橫軸是併發數,縱軸是 OLTP 的性能,藍色、黃色、綠色這些是 OLAP 的併發數。這個實驗的目的就是在一套系統上既跑 OLTP 又跑 OLAP,同時不斷提高 OLTP 和 OLAP 的併發壓力,從而查看這兩種 workload 是否會互相影響。能夠看到在 TiDB 這邊,同時加大 OLTP 和 OLAP 的併發壓力,這兩種 workload 的性能表現沒有什麼明顯變化,幾乎是差很少的。可是,一樣的實驗發生在 MemSQL 上,你們能夠看到 MemSQL 的性能大幅衰減,隨着 OLAP 的併發數變大,OLTP 的性能降低比較明顯。

接下來是 TiDB 在一個用戶實際業務場景的例子,在進行 OLAP 業務的查詢的時候,OLTP 業務仍然能夠實現平滑的寫入操做,延遲一直維持在較低的水平。

將來在哪裏

Snowflake

Snowflake 是一個 100% 構建在雲上的數據倉庫系統,底層的存儲依賴 S3,基本上每一個公有云都會提供相似 S3 這樣的對象存儲服務,Snowflake 也是一個純粹的計算與存儲分離的架構,在系統裏面定義的計算節點叫 Virtual Warehouse,能夠認爲就是一個個 EC2 單元,本地的緩存有日誌盤,Snowflake 的主要數據存在 S3 上,本地的計算節點是在公有云的虛機上。

這是 Snowflake 在 S3 裏面存儲的數據格式的特色,每個 S3 的對象是 10 兆一個文件,只追加,每個文件裏面包含源信息,經過列式的存儲落到磁盤上。

Snowflake 這個系統最重要的一個閃光點就是對於同一份數據能夠分配不一樣的計算資源進行計算,好比某個 query 可能只須要兩臺機器,另一個 query 須要更多的計算資源,可是不要緊,實際上這些數據都在 S3 上面,簡單來講兩臺機器能夠掛載同一塊磁盤分別去處理不一樣的工做負載,這就是一個計算與存儲解耦的重要例子。

Google BigQuery

第二個系統是 BigQuery,BigQuery 是 Google Cloud 上提供的大數據分析服務,架構設計上跟 Snowflake 有點相似。BigQuery 的數據存儲在谷歌內部的分佈式文件系統 Colossus 上面,Jupiter 是內部的一個高性能網絡,上面這個是谷歌的計算節點。

BigQuery 的處理性能比較出色,每秒在數據中心內的一個雙向的帶寬能夠達到 1 PB,若是使用 2000 個專屬的計算節點單元,大概一個月的費用是四萬美金。BigQuery 是一個按需付費的模式,一個 query 可能就用兩個 slot,就收取這兩個 slot 的費用,BigQuery 的存儲成本相對較低,1 TB 的存儲大概 20 美金一個月。

RockSet

第三個系統是 RockSet,你們知道 RocksDB 是一個比較有名的單機 KV 數據庫,其存儲引擎的數據結構叫 LSM-Tree,LSM-Tree 的核心思想進行分層設計,更冷的數據會在越下層。RockSet 把後面的層放在了 S3 的存儲上面,上面的層實際上是用 local disk 或者本地的內存來作引擎,自然是一個分層的結構,你的應用感知不到下面是一個雲盤仍是本地磁盤,經過很好的本地緩存讓你感知不到下面雲存儲的存在。

因此剛纔看了這三個系統,我以爲有幾個特色,一個是首先都是自然分佈式的,第二個是構建在雲的標準服務上面的,尤爲是 S3 和 EBS,第三是 pay as you go,在架構裏面充分利用了雲的彈性能力。我以爲這三點最重要的一點是存儲,存儲系統決定了雲上數據庫的設計方向。

爲何 S3 是關鍵?

在存儲裏邊我以爲更關鍵的多是 S3。EBS 其實咱們也有研究過,TiDB 第一階段其實已經正在跟 EBS 塊存儲作融合,但從更長遠的角度來看,我以爲更有意思的方向是在 S3 這邊。

首先第一點 S3 很是划算,價格遠低於 EBS,第二 S3 提供了 9 個 9 很高的可靠性,第三是具有線性擴展的吞吐能力,第四是自然跨雲,每個雲上都有 S3 API 的對象存儲服務。可是 S3 的問題就是隨機寫入的延遲很是高,可是吞吐性能不錯,因此咱們要去利用這個吞吐性能不錯的這個特色,規避延遲高的風險。這是 S3 benchmark 的一個測試,能夠看到隨着機型的提高,吞吐能力也是持續的提高。

如何解決 Latency 的問題?

若是要解決 S3 的 Latency 問題,這裏提供一些思路,好比像 RockSet 那樣用 SSD 或者本地磁盤來作 cache,或者經過 kinesis 寫入日誌,來下降整個寫入的延遲。還有數據的複製或者你要去作一些併發處理等,其實能夠去作 Zero-copy data cloning,也是下降延遲的一些方式。

上述例子有一些共同點都是數據倉庫,不知道你們有沒有發現,爲何都是數據倉庫?數據倉庫對於吞吐的要求實際上是更高的,對於延遲並非那麼在乎,一個 query 可能跑五秒出結果就好了,不用要求五毫秒以內給出結果,特別是對於一些 Point Lookup 這種場景來講,Shared Nothing 的 database 可能只須要從客戶端的一次 rpc,可是對於計算與存儲分離的架構,中間不管如何要走兩次網絡,這是一個核心的問題。

你可能會說沒有關係,反正計算和存儲已經分離了,大力出奇跡,能夠加計算節點。可是我以爲新思路不必這麼極端,Aurora 是一個計算存儲分離架構,但它是一個單機數據庫,Spanner 是一個純分佈式的數據庫,純 Shared Nothing 的架構並無利用到雲基礎設施提供的一些優點。

好比說將來咱們的數據庫能夠作這樣的設計,在計算層其實帶着一點點狀態,由於每臺 EC2 都會帶一個本地磁盤,如今主流的 EC2 都是 SSD,比較熱的數據能夠在這一層作 Shared Nothing,在這一層去作高可用,在這一層去作隨機的讀取與寫入。熱數據一旦 cache miss,纔會落到 S3 上面,能夠在 S3 只作後面幾層的數據存儲,這種作法可能會帶來問題,一旦穿透了本地 cache,Latency 會有一些抖動。

這種架構設計的好處:首先,擁有對實時業務的數據計算親和力,在 local disk 上會有不少數據,在這點上不少傳統數據庫的一些性能優化技巧能夠用起來;第二,數據遷移其實會變得很簡單,實際上底下的存儲是共享的,都在 S3 上面,好比說 A 機器到 B 機器的數據遷移其實不用真的作遷移,只要在 B 機器上讀取數據就好了。

這個架構的缺點是:第一,緩存穿透了之後,Latency 會變高;第二,計算節點如今有了狀態,若是計算節點掛掉了之後,Failover 要去處理日誌回放的問題,這可能會增長一點實現的複雜度。

還有不少值得研究的課題

上面的架構只是一個設想,TiDB 其實還不是這樣的架構,但將來可能會在這方向去作一些嘗試或者研究,在這個領域裏面其實還有不少 open question 咱們尚未答案,包括雲廠商、包括咱們,包括學術界都沒有答案。

如今有一些研究的課題,第一,若是咱們要利用本地磁盤,應該緩存多少數據,LRU 的策略是什麼樣子,跟 performance 到底有什麼關係,跟 workload 有什麼關係。第二,對於網絡,剛纔咱們看到 S3 的網絡吞吐作的很好,什麼樣的性能要配上什麼樣的吞吐,要配多少個計算節點,特別是對於一些比較複雜查詢的 Reshuffle;第三,計算複雜度和計算節點、機型的關係是什麼?這些問題其實都是比較複雜的問題,特別是怎麼用數學來表達,由於須要自動化地去作這些事情。

即便這些問題都解決了,我以爲也只是雲上數據庫時代的一個開始。將來在 Serverless,包括 AI-Driven 幾大方向上,怎麼設計出更好的 database,這是咱們努力的方向。最後引用屈原的一句話,就是路漫漫其修遠兮,咱們還有不少事情須要去作,謝謝你們。

相關文章
相關標籤/搜索