CynosDB技術詳解——架構設計

騰訊雲加社群發表於2018-12-20

本文由騰訊雲資料庫發表

前言

CynosDB是新一代分散式資料庫,100%相容MySQL和PostgreSQL,支援儲存彈性擴充套件,一主多從共享資料,效能更是超越社群原生MySQL和PostgreSQL。CynosDB採用share storage架構,其彈性擴充套件和高價效比的基石則是CynosDB File System(簡稱CynosFS):一款騰訊雲自研的使用者態分散式檔案系統。本文旨在從整體上講述CynosDB和CynosFS的核心架構設計。

挑戰與應對

CynosDB是公有云原生架構的,其核心思想是在資源池化的基礎上實現公有云高價效比、高可用性以及彈性擴充套件等諸多優勢。實現資源池化的最大技術挑戰是高效、穩定的彈性排程能力,該能力也是公有云產品高可用性的基石。計算、網路和儲存是公有云三大類Iaas產品,前面兩類都有比較成熟的彈性排程架構,唯獨儲存產品例外。究其根本還是資料排程的代價太高。資料庫是典型的計算+儲存的產品,要做到資源池化需要:

**l儲存與計算分離:**這樣計算資源(主要包含CPU和記憶體)就可以使用現有成熟的容器、虛擬機器等技術實現資源池化

l**分散式儲存:**將資料分割成規格化的塊,引入分散式排程系統,實現儲存容量和IO的彈性排程,從而實現儲存資源的池化

那麼對於資料庫產品來說,是否有現成架構可以很好的滿足以上兩個需求呢。我們發現虛擬機器+分散式塊儲存(雲盤)的方案非常合適,目前主流公有云平臺也都有非常成熟的產品。騰訊雲今年早些時候推出的MySQL基礎版以及AWS上的RDS都是基於這種架構。圖1簡單描述了這種架構:

img

圖 1

但該架構有如下不足:

l網路IO重:可以看到就1個資料庫例項,就有大量資料需要寫到雲盤,這些資料主要包括:WAL LOG、頁資料、防止頁部分寫的Double Write或者Full Page Write。除此之外,雲盤還要將這些資料做多個備份

l主從例項不共享資料:一方面浪費了大量儲存,另一方面進一步加重了網路IO

這些不足導致基於該架構的資料庫產品在系統吞吐能力上無法與基於物理機部署的主從架構競爭,而且延遲也受到很大的挑戰,這對OLTP類業務的影響非常明顯。同時每個資料庫例項都單獨擁有一份(實際可能是2-3份)儲存,成本也很高。

CynosDB針對這兩個不足,採用瞭如下設計:

l日誌下沉: WAL LOG從邏輯上已經包含了資料的所有變動,CynosDB將WAL LOG下沉到儲存層,資料庫例項就只需要將WAL LOG寫到儲存層,不再需要寫頁資料(頁資料以及Double Write或Full Page Write),同時這個WAL LOG也作為RAFT協議的日誌來完成多個資料備份的同步,進一步減少了網路IO。

**l主從例項共享資料:**CynosDB的主從例項共享共一份儲存資料,進一步減少了網路IO,同時極大的減少了儲存容量

循著這兩個解決思路,我們對傳統基於雲盤的架構進行優化,就有了CynosDB如下架構:

img

圖 2

圖中元件包括:

l**DB Engine:**資料庫引擎,支援一主多從。

l**Distributed File System:**使用者態分散式檔案系統,主要提供分散式的檔案管理,負責將檔案的讀寫請求翻譯為對應的BLOCK讀寫

l**LOG/BLOCK API:**Storage Service提供的讀寫介面,對於讀寫請求有不同處理:

n寫請求:將修改日誌(等價於WAL LOG)通過LOG API傳送到Storage Service

n讀請求:直接通過BLOCK API讀取資料

l**DB Cluster Manager:**負責一主多從DB叢集的HA管理。

l**Storage Service:**負責日誌的處理、BLOCK資料的非同步回放、讀請求的多版本支援等。同時還負責將WAL LOG備份到Cold Backup Storage

l**Segment(Seg):**Storage Service管理資料BLOCK和日誌的最小單元(10GB),也是資料複製的實體。圖中同樣顏色的3個Seg實際儲存同一份資料,通過一致性協議(Raft)進行同步,我們叫做Segment Group(SG)。

l**Pool:**多個SG從邏輯上構成一個連續的儲存資料BLOCK的塊裝置,供上層的Distributed File System分配使用。Pool和SG是一對多的關係。

l**Storage Cluster Manager:**負責Storage Service以及Segment Group 的HA排程,以及維護Pool和SG的對應關係。

l**Cold Backup Service:**接收到WAL LOG後,進行增量備份,根據增量備份,可以靈活的生成全量備份和差異備份

可以看到,上面中除了DB Engine和DB Cluster Manager外的所有模組構成了一個與資料庫引擎無關的使用者態分散式檔案系統,我們命名為:CynosFS

日誌下沉和非同步回放

這裡CynosDB借鑑了AWS Aurora論文中日誌即資料庫的思想,將WAL LOG下沉到Storage Serivce,計算層只寫WAL LOG,而由Storage Serivce非同步地將WAL LOG應用到對應的BLOCK上,在減少寫IO的同時,也是Storage Serivce提供MVCC讀能力的基礎。而MVCC是主從節點共享儲存的基礎。Storage Serivce中的資料和日誌都是以Segment為單元進行管理的,圖3描述了寫的基本流程:

img

圖 3

1.接收到更新日誌,寫到磁碟,並行發起第2步

2.發起RAFT日誌複製

3.RAFT多數派提交成功,返回寫日誌成功

4.非同步的將日誌記錄掛載到對應資料BLOCK的更新鏈上

5.合併更新鏈中的日誌記錄到資料BLOCK

6.將日誌備份到冷備系統

7.回收無用日誌

這裡第4步會對更新的資料BLOCK形成1個更新鏈,從而支援資料BLOCK多個版本的讀,進而提供MVCC能力。通過控制第5步的合併進度,就可以控制MVCC的起始視窗。

同時CynosDB還將頁面CRC等操作放到了儲存服務中,充分利用儲存伺服器的CPU資源

MVCC實現

CynosFS的MVCC能力是CynosDB一主多從架構的基礎,本小節會詳細描述其執行機制。

首先我們引入一系列概念:

lMini-transaction(MTR):就像資料庫事務用來保證事務的ACID特性,MTR用來保證磁碟上頁資料的ACID特性。舉個例子,1個B+樹的插入操作,在造成節點分裂的情況下,最多會修改3個資料頁,這3個資料頁的修改需要當做1個事務來處理,這就是MTR。資料庫例項在磁碟上的資料是按照MTR為最小單元進行更新的

lWrite Ahead Log(WAL LOG):關聯式資料庫常用的保證資料一致性的技術。WAL LOG是一個增量日誌流水,裡面的日誌記錄(Log Records)儲存了頁面修改操作。由於CynosFS是與具體資料庫引擎無關的分散式檔案系統,其WAL LOG中記錄的是對資料BLOCK的二進位制修改,是物理日誌

lLog Sequence Number(LSN):WAL LOG中每條Log Record都會有1個唯一標識的序列號,從1開始,按Log Record產生的連續單調遞增。

lConsistency Point LSN(CPL):一個MTR可能對應多個磁碟資料頁的修改,相應的會產生多條日誌記錄,這批日誌記錄中的最後1條(也就是LSN值最大的1條)標識為CPL,這條日誌記錄對應了一個磁碟上的資料狀態,該狀態表示1個MTR的完整應用,也是MVCC的讀一致性狀態

lSegment Group Complete LSN(SGCL):1個資料庫例項的資料頁會分佈到多個SG上,因此每個SG只會持有部分日誌記錄,SCL表示該SG已經將所有小於等於SCL的日誌記錄持久化到磁碟上了。對於CynosFS來說,因為SG採用了Raft協議,SCL就是Raft的CommitIndex。

lPool Complete LSN(PCL):表示構成該Pool的所有SG已經將小於等於PCL的日誌持久化到磁碟上。因為LSN是連續單調遞增的,這也要等價於中間沒有空洞

lPool Consistency Point LSN(PCPL):不大於PCL的最大的CPL。邏輯上表示:已經持久化到磁碟的可提供MVCC讀一致性的點。

首先主例項對所有資料頁的修改都經過Distributed File System的轉換,形成Pool級別的日誌,並附帶連續單調遞增的LSN,分發到不同的SG。SG會在完成Raft Commmit後推進自己的SGCL並返回,主例項根據所有SG的完成情況,推進PCL和PCPL。下面我們通過2幅圖描述PCL和PCPL的推進過程:

img

圖 4

首先該Pool由2個SG構成,每個SG中有3個Segment,儲存同一份資料。當前有LSN為1~8的日誌已經持久化到2個SG中,其中1、3、4、7在SG A上,2、5、6、8在SG B上。這8條日誌屬於3個MTR,分別是:MTR-x(1、2、3),MTR-y(4、5),MTR-z(6、7、8),其中3和5都是CPL,表示MTR-x和MTR-y對應的日誌已經全部持久化了,8不是CPL,說明MTR-z後續還有日誌記錄。按照上面的定義,此時PCL為8,而PCPL為5

img

圖 5

圖5中,MTR-z的1條日誌CPL9被持久化到SG A,按照定義,此時PCL和PCPL都更新到了9。

這裡主要指從例項的讀流程。從例項具有自己的記憶體資料,在主例項更新了資料後,需要同步更新從例項的記憶體資料,否則會出現不一致的情況。主例項會將日誌記錄以及最新的PCPL值推送給從例項。因此從例項的PCPL值會較主例項有所延遲。這個PCPL值決定了從例項上所有事務能讀到的最後1個MTR。同時為了減少從例項的延遲,主例項可能不等PCPL值推進先把日誌推送到從例項,因此從例項需要保證大於本地PCPL值的那些日誌不被應用。從例項對這些更新日誌的處理方式有兩類:如果對應修改的資料頁在Buffer Pool中,則應用此日誌更新到對應資料頁,否則直接丟棄。最後從例項上的讀事務在每次訪問資料頁時(不管直接從Buffer中獲取到,還是從Storage Service獲取),因為可能一次讀入多個頁,所以需要取當前的PCPL值為Read Point LSN(簡稱:RPL),用RPL達成到一致性讀(因為PRL是一個PCPL值,其一定能保證MTR的完整性)。CynosDB支援一主多從,每個從例項上都會有很多讀事務,這些讀事務都具有自己的RPL,所有這些RPL中最小的我們稱之為Min-RPL(簡稱:MRPL),那麼在MRPL和PCPL之間可能會有多個CPL點,不同讀事務的RPL可能在這個區間的任何1個CPL點上。因此Storage Service要能支援讀取在這個區間內任意CPL點的資料,也就是MVCC。CynosDB使用資料頁+更新日誌鏈的方式來實現。

最後讓我們回到圖3,SG需要定期回收無用的日誌記錄,我們可以看到,所謂無用的日誌記錄就是其LSN值小於MRPL的那些。而大於等於MRPL的那些日誌因為要用來支援MVCC,所以必須保留。

事務提交

一個資料庫事務由多個MTR組成,最後1個MTR的最後1條日誌的LSN(必然也是個CPL)我們稱之為Commit LSN(簡稱:CLSN)。為了提升效率,日誌到Storage Service的推送採用非同步流水線的方式,同時按照SG進行分組並行推送。全域性來看,因為是並行的,所以可能會有亂序,但推送到某個SG上的日誌一定是按照LSN單調遞增的(不連續)。隨著PCPL的推進,一旦PCPL值大於某個事物的CLSN,該事物就可以完成Commit操作了。

崩潰恢復

首先,CynosDB會持續的儲存主例項的PCPL,這個PCPL的備份值我們稱之為:Last PCPL(簡稱:L-PCPL)。CynosDB需要保證L-PCPL值的更新足夠快,以確保那些大於L-PCPL的日誌記錄沒有被回收。在此前提下,我們通過如下步驟實現崩潰恢復:

img

圖 6

首先,新的主例項獲取到L-PCPL值為3。該例項由2個SG組成,其中SG A中已經持久化了日誌(1、4、5),而SG B中持久化了日誌(2、3、6、8)。

img

圖 7

主例項向2個SG讀取大於3的所有日誌LSN,獲取到SG A的4、5以及SG B的6、8。這樣形成了3、4、5、6、8的日誌流。按照定義,因為沒有LSN為7的日誌,所以8是無效的,其次6不是CPL,所以6也是無效的,這樣就計算出了最新的PCPL值為5。然後將新的PCPL值推送給所有的從例項。

img

圖 8

最後,主例項將新的PCPL=5推送給所有SG,以便其將大於5的所有日誌都清理掉。

經過上面三步,整個資料就回到了PCPL=5這個一致性的點。主例項和從例項就可以提供服務了。

持續備份

實際上,在CynosDB中,幾乎不需要全量的備份操作,只要保證SG的WAL LOG在回收前,被增量儲存到了冷備系統中就行了。因為邏輯上WAL LOG是包含了所有資料的修改操作,我們可以使用增量的WAL LOG,按照客戶需求,生成全量備份和差異備份。而這些操作都可以是由另一套獨立的系統基於增量備份資料離線處理的,對CynosDB的線上系統不會造成任何的影響。另外我們還需要對例項的狀態配置資訊進行備份,以便恢復時能獲取到相關資訊。

【騰訊雲100元無門檻代金券開搶】各位新老鄉親,騰訊雲資料庫年終福利來啦~為了更好地為廣大開發者提供服務,資料君誠摯的邀請您參與本次有獎調研,說你最想說的話,用最好用的資料庫!問卷會佔用您兩分鐘左右的時間,回答完畢後將有機會獲得騰訊雲100元無門檻代金券,限雲資料庫和雲伺服器使用哦~如您抽中獎品,請在頁面填寫手機號,該手機號將用於接收兌換券碼。數量有限先到先得,12月15日抽獎入口將關閉,快點選參與吧!

此文已由作者授權騰訊雲+社群釋出,更多原文請點選

搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!

相關文章