新一代雲原生數據庫暢想

語言: CN / TW / HK

雲與分佈式是數據庫發展的兩大趨勢,那雲時代下新一代數據庫會是什麼樣的呢?騰訊雲數據庫專家工程師竇賢明講師給大家分享了自己的暢想, 基於冷熱分級存儲與ServerlessDB結合的新一代數據庫 。基於騰訊雲數據庫TDSQL-C PostgreSQL在雲原生這條路上的一些探索,重點從Serverless 數據庫和分級存儲(冷熱分離)的設計與實現兩個方面進行分享。內容主要分為四個部分:

第一部分:介紹雲時代的數據庫的背景;

第二部分:探討雲上數據庫進化的邏輯是什麼、方向是什麼;

第三部分:描述Serverless數據庫具體是什麼樣子;

第四部分:雲原生數據庫在存儲方向上的進一步演進,分級存儲所達到的效果、在冷熱分級等場景下的一些用例。

公眾號福利 :本期講師課件獲取方式, 騰訊雲數據庫 公眾號後台回覆“ 5.7內核課件 ”即可。

雲時代的數據庫

在過去一二十年間,整個關係型數據庫行業最大的變化只有兩個,一個是 ,一個是 分佈式

雲時代,對數據庫產生了一個非常大的一個衝擊,或者説變化。就Gartner近期數據,雲上數據庫的份額也已經趕上並即將超過on promise(傳統方式)的產值。

那雲時代的數據庫是一個什麼樣子呢 ?以騰訊雲的TencentDB for PostgreSQL為例。雲數據庫的第一個階段,其實是在將傳統數據庫搬到雲上來。首先,最開始部分是基礎環境,比如説硬件資源、網絡、存儲之類;在此基礎上,進行一些虛擬化,這些是雲本身具備的能力;在用户側,資源準備好了之後,是一個資源的管理分配和運行環境的準備;然後是做雲數據庫託管的一些事情,包括部署、HA、備份恢復等,還有監控這些;那整體上還是一個PaaS平台這麼一個事情。這個過程中,整體來講還是將傳統的主備搬到一個雲環境這麼一個過程,其實並沒有對數據庫的內核或者説數據庫的架構產生一些根本性的變化。

這其實是在過去幾年雲數據庫或雲的一個演進的第一階段,把原來的數據庫運維,以雲的方式託管起來、在雲上使用起來。

那在這期間是怎樣一個實現方式呢?首先,會有一個雲數據庫的一個部署,即實例進程運行在虛擬機裏面、存儲則放在一個雲盤存儲上;然後會建立一個備庫,主備之間通過Replication實現數據的複製,通過兩份完整的數據節點實現高可用。這一點,與當前物理環境並沒有什麼本質上的變化,即 一主一備 的方式。

即使如此(簡單的實現),雲數據庫相比傳統數據庫仍然會有很多的優點。

第一, 成本更低 ,當前主要是雲本身的特質帶來的;第二點就是 擴容能力更好 ,比如説它擴容能力好的是在於説存儲這裏可以動態擴容,計算這裏可以更為輕量的擴縮容;第三點,是 體驗上也有非常大的提升

然而,仍然有些問題沒有解決,尤其是在站在雲的視角來看。當有越來越多的數據庫實例跑在一起的時候,發現這個 成本的增長是線性 的,成本上是沒有去得到一些根本性的降低。

就一主一備的情況來説,有兩份完全一樣的數據;當我們再新加一個RO(Read Only節點,僅用於讀請求)的時候,還會再加一份完整的數據。存儲成本沒有根本性的收斂,根據RO的數量線性增長。

而另外一種情況, 網絡存儲 成為一個瓶頸。再拿這個例子來説,每次讀寫都會對網絡形成一個吞吐,且隨着RO數量增加也是一個線性增長,對網絡總流量造成較大的壓力。

RO節點(Replica)的建設時間成本也是一個問題 。多添加一個RO節點,就是多一份數據,是完整的一個複製(對應存儲上的三副本),複製時間較長。

雲原生進化

雲原生數據庫( Cloud Native Database )的提出,是 為了解決原來傳統架構下無法解決的這些問題 ,基於雲基礎設施重新設計與實現所提出的一個解決思路。

那其中核心的解決思路是什麼?答案就是 存算分離

可以思考一個問題:主節點和 RO 節點各自有一份完整的存儲,且各自都有三副本。為什麼我們這些節點不共用同一份數據呢?這裏很容易就想到一點,就是我們把所有節點的數據都放在遠端分佈式存儲上,不再本地存放。這樣的話,存儲就可以實現僅有一份數據(三個副本),而計算仍然是多節點。

把數據庫內部拆開來看,基本上來講分為兩部分:一個是 存儲層 ,一個是 計算層 。計算層一般包含詞法解析、語法解析、語義解析、查詢重寫、優化器等。下一層則是數據緩存,相對設計邏輯比較簡單一些,這部分一般不單獨列;中間這個事務層,保證數據存儲、讀取的正確性;最下層storage層負責跟實際的存儲硬件打交道。

既然要把所有節點的數據放在同一個分佈式存儲(租户)上,就需要將數據庫內核的引擎和存儲部分拆開到兩個地方運行,存儲的部分放在分佈式存儲系統內運行,把引擎的部分放在計算節點中運行。表現為所有的RW、RO都沒有實際的數據,只需要內存和CPU的資源拉起來即可,這個時候RO啟動的效率就非常高,本身就很輕。RO則通過Replication從RW拿到更新的修改,去更新它內存中的緩存。

那前面也有講到網絡成為瓶頸的問題,需要分別針對 RW和RO來説明。

針對 RW ,有一個 WAL的概念,即Write Ahead Log,所有數據的變更都會記錄在這裏。這裏做一個極端假設,假如從數據庫被初始化之後所有的WAL都被保留、且有一台非常非常強大的計算機,在每次讀取數據時,都將最開始到最新的所有WAL全部重放到當前時刻,其實是可以得到與當前數據庫中完全一致的數據。這一點,可以描述為Log is Database。

如果 WAL 能夠對應一份完整的數據,那麼在寫入存儲時,可以不寫入數據部分、僅寫入 WAL。存儲層在收到WAL之後,基於存儲上已有的數據部分,對WAL進行不斷的重放,就可以實現數據不斷的更新,保證數據的一致性。這裏具體的實現較為複雜,不再作展開。 達到的效果就是,至少減少一半的網絡流量

RO 剛才已經簡單説過一些,在通過 Replication獲取到WAL之後,會對緩存中數據進行更新。當需要從存儲上讀取數據時,根據該數據頁的時間戳,將其後的WAL更新上去,也因此,RO需要在內存中緩存一份近期的WAL,得到一個保證一致性的最新數據頁。

整體來講,通過以上的機制,實現數據存儲在分佈式存儲上主備節點採用同一份存儲,達到RO節點增加存儲成本不變的效果。也因此,RO的數量支持最大到15個。

存儲計算分離之後,剛開始優勢未必特別明顯,在使用上和前面的雲數據庫沒有本質的區別,用户體驗基本一致。效果會隨着使用的加深而逐步體現出來。

第一, 擴縮容的效率完全不一樣 ,原本在擴容的時候,有可能出現空間不夠需要遷移,導致時間成本非常高。計算變得特別輕,可以快速拉起、關閉,遷移效率極高,不用擔心擴容時需要遷移的情況。

可用性、可靠性 等方面,因為所有的狀態都存儲在分佈式存儲中,計算節點的啟停(可用性),不會影響存儲上數據的可靠性,因此在計算節點出現故障時,可以隨意關閉老節點、啟動新節點,不用擔心會丟失數據,可用性方面達到了較高的保證;存儲上數據有三副本,保證了數據的可靠性;且多個節點共用同一份存儲,整體成本也更低。

針對計算來説,計算節點被做得輕量、可以便捷地啟停,當這份便捷性達到一定水平的時候,就會引起質變。

極致彈性

正常來講,業務有高峯低谷,比如訂餐系統。一家餐飲公司的訂單系統,肯定是有高峯和低谷,基本上是三餐的時候比較高,夜裏幾乎為零。那沒有業務在運行的時候,為什麼還要這個計算節點付錢?在傳統方式下,需要準備一台物理機; 在雲數據庫形勢下,則以實例為單位,計費的粒度仍然較粗。那怎麼去做呢

這裏可以考慮這樣的產品形態,在用户端呢, 計算節點在不用時不計費,在真正使用時再拉起並開始計費;且擴容也不再需要用户操作,由後端自動根據負載來做調整,在不用時自動將資源佔用降為0 。存儲空間也類似。原本客户在購買了一個100GB的存儲空間,會一直按100GB來計算費用,但實際可能並沒有真正用到那麼多。這裏可以實現為僅僅為實際佔用的空間付費。

正常情況下,數據庫實例處於休眠狀態;當SQL到達時,將計算節點拉起來,然後執行SQL。同時,RO也可以加進去一起參與,就是可以一次拉起一個或者多個計算節點,在這些節點上做負載均衡。當沒有SQL在運行超過一定時間,比如超過五秒鐘、十秒鐘沒有SQL在運行,計算節點可以直接關閉,也因為業務沒有在運行,也感知不到負面影響。而 計費成本上,則獲得較大的降低

舉例來説,比如餐廳運營的高峯時間段(如中午時間),SQL會一直進來一直使用,後端計算節點則持續存在。當資源用滿達到一定閾值,將自動升配;那中午過後,不再有請求,計算節點則會被關閉、也不再計費,計算成本降為0。

演進到當前, 計算節點最細粒度可以做到一秒級別的計費 。據內部數據來看,有不少客户的業務一天只花可能不到幾塊錢、甚至幾毛錢都有,一個月可能就花幾十塊錢。而像傳統物理機的方式起碼十萬起,雲數據庫也要每月幾百、幾千塊。這是一個巨大的飛越!

分級存儲

花分兩朵,各表一支。前面是計算節點的演進, 存儲節點又該如何演進

存儲的演進持續在進行,比如性能、壓縮等。此處僅針對數據的存儲成本。數據大致可以分為幾層:熱數據、温數據、冷數據。熱數據放在內存緩存裏,價格最貴、性能最好。然後,大量的數據放在分佈式存儲上,那冷數據該如何處理?

熱、温、冷的劃分,主要基於的是訪問頻率、量和性能要求。冷數據,一般定義不經常訪問的數據,比如歷史訂單、歷史日誌等。當前 TDSQL-C PostgreSQL的存儲規模支持最高128TB,絕大部分情況下足夠業務使用。冷數據比較多、不常訪問,放在 TDSQL-C PostgreSQL的存儲中又較貴,該如何處理?

答案是COS。COS是騰訊雲的 對象存儲服務 ,數據存儲成本要低於TDSQL-C PostgreSQL的高性能存儲盤。温熱的數據,或者説時刻需要用到的數據,還是要放在分佈式存儲上正常使用,但針對時間較老、不大訪問的冷數據,可以放在COS中,並通過同樣的一套SQL語言、表結構來訪問。

為實現這一點,TDSQL-C PostgreSQL 封裝了COS的訪問接口 ,通過與常規數據表完全一樣的使用方式,達到對COS上數據文件進行訪問的目的。

這裏舉一個具體的例子:第一步,創建一個Server,指定COS的信息,包括id、key、endpoint、文件等;第二步,在該Server上創建表;然後就可以通過讀這張表實現對COS上文件的讀取。異構存儲的訪問,基本上分為三部分,計算、元數據(表結構等)、存儲格式。Server/表定義這裏,即實現了元數據的維護,存儲格式上當前支持CSV。具體的執行邏輯可以通過執行計劃查看。

另外一個例子,是更復雜的一些用法,比如:Table a和Table b都是本地表,數據存放在存儲上,再建一張COS表,就可以直接對這三張表做關聯運算。這比較適合報表類的場景,比如以賬户信息為維度統計歷史訂單類的報表。

還有一個例子,就是 分區表 。還是Table a和Table b,放在分佈式存儲上,一張 COS表,三張表放在一起作為一張分區表的三張子表。PostgreSQL有非常強大的分析能力,當基於分區字段做過濾的時候,會根據分區字段做裁剪;再配合分區表的Time to live的功能,比如Table a和Table b是正常的按時間分區,Table c則是 COS 表,可以實現同樣一張(分區)表,部分放在存儲、部分放在COS 上的效果。

專家答疑

1. 存儲計算分離之前PostgreSQL用的什麼高可用方案?

答:原先一主一備形態下,高可用方案是內部自研的一套,基本分為探測、策略和執行三個步驟。

2. 主庫和備庫要做到同步,那資源豈不是很浪費?

答:主庫和備庫的數據同步,主要是為了解決 RO、備庫上內存中熱數據的持續更新,一定程度上是為了提升備庫的性能和數據一致性。如果不在RO上保持緩存,性能會較為糟糕;若保留了緩存,則需要對這些緩存持續更新,以保證數據一致。

3. 更新操作多的情況呢?

答:主備間複製採用的是物理複製的方式,只是將數據頁上的變更部分發送到備庫上,在數據頁上重做,這種方式較為高效、延遲較低。

4. RO先讀取數據頁,再應用WAL,會不會出現讀延遲?

答:會有一定延遲,但這不會成為一個問題。

主備方式在當前硬件、網絡情況下,必然會存在一定延遲,收斂在一定範圍內即可。若要保證完全無延遲,也不是做不到,代價過於高昂、不值得;

WAL 的重放改為以頁為單位,相比原來的方式更為高效,延遲反而更低;

主備間應該通過 Proxy 實現全局一致性;

通過以上措施綜合解決主備延遲帶來的影響。

5. 目前是一個RW,多個RO,怎麼才能擴展寫能力呢?

答:當前寫能力很多時候不會成為一個瓶頸。在僅寫入 WAL 之後,網絡IO是制約寫能力的核心因素之一,當前最新可以到達 100Gb/s 網絡,在存儲側又被分發到多台機器上,少有多業務能將這兩個地方都打到瓶頸上。當趨勢出現的時候,我們也可以考慮採用多寫的方式來承接,這就是另外一個故事了。

6. 既然是share存儲了,為什麼還要master到replica的複製?

答:參考問題二,主要是為了解決RO上的查詢性能問題,需要在緩存中保持數據。

7. 存算分離後怎麼解決謂詞下沉技術和存儲節點計算瓶頸問題?所有數據都從存儲拉到計算節點計算?

答:這裏其實不用過於擔優性能的問題。比如,現在有一個RW15個RO,一台機器機器大約 96vCore,16台加起來一共1536,很難有業務能吃掉這麼多CPU,計算資源在很多時候是足夠的。

但謂詞下推確實也適合這種架構,減少網絡開銷,實現的方式是將where條件的描述下發到存儲層,存儲層在返回數據之前對數據進行過濾。其中比較難的課題是存儲上計算資源的調度問題,這時候要看存儲機的硬件條件。這也是存儲計算分離一個價值點,存儲層可以針對存儲層定製相關的機型,可能就要去配合一些新硬件,比如FPGA、GPU之類的

8. 沒明白存算分離的意思,存儲單獨存儲,計算的話指的是每次查詢都需要新拉起一個實例去存儲中拉取數據麼?

答:是也不是。這裏可以保持一個實例一直運行,這樣有部分數據是在內存中,沒有用到存儲上的數據時不用從存儲上讀取,沒有的時候從存儲上讀。缺點是,計算節點會持續計費。

核心還是成本。

這裏比較好的玩法,是在每次執行SQL的時候才拉起實例,在超過閾值時間不再使用後,將其關閉,以節省資源。Serverless形態解決的是計費和調度的問題,存儲和計算分離之後,存儲層可以單獨計費、計算成本按實際用量計算,可以極大節省成本。

對於很多業務來講,尤其是有高峯低谷的業務,有非常大的成本降低的效果。並且,也解決了雲數據庫架構上沒有解決的問題,從而實現更高可用性、更好的用户體驗。

9.分級存儲,如果數據放到對象存儲上面,這種存儲方式只適合存儲歸檔數據,不適合有update,delete的數據。

答:這個問題比較專業。 級存儲只解決一類的場景,數據量比較大、不改不刪、偶爾讀取,比如歸檔類的數據,放在數據庫內這種高性能存儲上成本又高,説到底還是成本問題。 比如有很多行業有安全性的要求,要求至少保留兩年以上的歷史數據; 而這些數據都不會訪問,但時不時的還會查一下。

這個時候,如果用另外一套存儲、另外一套引擎、另外一套機器,維護成本是相當高的。我們提供這種方式,一部分相對冷的數據放到COS來,但數據的管理和維護還是在數據庫中。因此,不適合刪改較多的場景。

10.計算節點下的存儲是不是有優化的方向,比如WAL放在計算節點上,用高速設備進行優化?

答:存算分離方案實現的一個核心思想,就是 Log is Database。通過將 WAL 寫到存儲、並在存儲中存放,達到數據寫入存儲的目的。

我理解這裏的問題是,是否可以先把 WAL 寫入本地、然後異步化寫入存儲中?這是一個有意思的思路,但這假設了一個前提,就是本地盤比分佈式存儲的吞吐能力更強。在當前的網絡、硬件條件下,這個假設已經不一定成立了。畢竟現在100Gb/s的網絡已經可以作為標配,再有RDMA的加持,網絡吞吐已經高於本地盤;且存儲側的寫入會分佈在多個節點上,也提升了吞吐。

關於作者

竇賢明,騰訊雲數據庫專家工程師,從事雲數據庫產品研發多年,從零到一主導研發多款雲數據庫、雲原生數據庫。目前負責 TDSQL-C PostgreSQL、TencentDB For PostgreSQL 的全棧研發工作,和TDSQL-C MySQL 的產品化研發工作。

-- 更多精彩 --

騰訊雲TDSQL-C重磅升級,性能全面領跑雲原生數據庫市場

關於雲原生數據庫的一切都在這裏了

點擊 閲讀原文 ,瞭解更多優惠