最近的幾年中,HTAP數據庫成為了一個時髦詞匯,言必稱HTAP也成了很多數據庫領域從業者的風潮。如何打造一款HTAP數據庫,從架構層面出發,去應對未來的變化,擁抱變化,也是很多數據庫公司所一直在探索的。
MatrixOne 是矩陣起源(MatrixOrigin)開源的一款超融合 HTAP 云原生數據庫,與業內諸多數據庫產品非常不同的點是,MatrixOne 的自研之路是從第一行代碼開始的。MO 的目標是打造一款極簡、高擴展性、高靈活性、高性價比的全新數據庫。
在過去的兩年里,MatrixOne經歷了一次架構的演進,更具有實驗性質的舊架構到面向未來的新架構,成為了諸多數據庫開發工程師與運維工程師的關注點,他們經歷怎樣的架構演進,這中間又有哪些值得借鑒的內容,將在本文中為大家一一揭曉。
早期架構的千層糕
MatrixOne作為一款開源分布式架構的數據庫,已有接近2年的生命歷程。我相信有很多社區老用戶,會對早期架構時SSB測試的高性能留有印象。而到了0.5版本發布之后,性能突然就大幅下滑。當時就有朋友問我,怎么還越做越回去了?我對他說,有個大動作,整個架構做了一個大規模的升級。
此時此刻,我覺得很有必要,對整個架構的演進升級,做一個完整的闡述。
如何界定MatrixOne的早期架構?明確地說,是指MatrixOne從0.1到0.4版本的架構,也是在2022年上半年之前,在各類推送中出現的那個架構。與其說這是一個架構,更不如說,這是一場實驗,通過一個架構,去探索出各種架構的不足,找到真正適合于與原生的HTAP分布式架構。

這個實驗的舊架構,有兩個顯著的特征:NewSQL與MPP。前者是基于Google當年的幾篇經典論文所衍生出的,也是今天很多數據庫產品的總思路。后者MPP,顧名思義,大規模并行處理,并行計算是它們的顯著特點。落地到MatrixOne的早期架構,又有了更具體的含義。
NewSQL
分布式架構:多節點的分布式數據庫服務器,每一臺服務器既包含了計算資源,又有各自的存儲節點,解決了傳統單機數據庫伸縮性和高可用問題。
多引擎:數據庫服務器中可能存在多個存儲引擎,不同的引擎特性不同,負責不同的場景。
MPP
并行計算:將任務并行地分散到多個服務器和節點上,在每個節點上計算完成后,將各自部分的結果匯總在一起得到最終的結果。
早期架構詳解

進一步拆解,將視角拉到MatrixOne Server內部,它又有著多個模塊,分工協同,完成整個分布式數據庫的功能。一共分為5個部分,前端、計算層、分布式框架、存儲層、元數據層。五個部分各自的功能與特性又各有不同。
SQL Frontend
亦稱SQL前端,是直接處理SQL語句的部分,它提供了如下功能:
提供MySQL兼容協議,確保MySQL的各類協議能夠被MatrixOne接收;
兼容MySQL的語法,對接收的SQL做符合MySQL的語法判斷。
Query Parser
是MatrixOne中對語法解析的功能模塊,它提供了如下功能:
SQL解析,對前端的SQL并轉化抽象語法樹;
方言支持,提供支持多種SQL方言基礎。
MPP SQL Execution
是實現MPP的SQL執行器,它提供了如下功能:
SQL加速,對SQL計算引擎的一些基礎操作的向量化加速,部分操作采用匯編改寫做加速;
Plan構建,使用獨有的因子化加速能力做SQL的Plan構建。
分布式框架
早期MatrixOne的分布式框架叫做MatrixCube,同樣是一個開源項目,它具備了如下組件與功能:
提供高可用、多副本、強一致與自動負載均衡;
提供分布式事務的支持能力(WIP);
提供基于Raft的副本調度機制,該調度器在代碼中稱為Prophet。
存儲層
早期的MatrixOne存儲層是一個擁有多個引擎的架構,多種存儲引擎互相分工協作,共同完成HTAP數據庫功能:
AOE引擎,Append only Engine,這是一個Append Only的列存引擎,不支持事務;
TPE引擎,Transaction Processing Engine,用于保存元數據Catalog;
TAE引擎,Transactional Analytical Engine,基于列存的HTAP引擎,會提供完整ACID能力及強大的OLAP能力。
元數據層是一個在早期MatrixOne架構中被每個其他模塊都頻繁調用的內容,保存在TPE引擎中,提供了全局的元數據的保存與讀取,是一個頻繁使用的模塊。
早期架構,何以不足?
作為一個早期的架構,更多的是承載了研發團隊早期的探索和研究,通過實驗架構,逐步探索出一條面向未來的架構。隨著開發進度的不斷推進,毫無意外地,舊架構的問題開始凸顯出來,并且隨著功能與性能的提升,愈發成為后續發展的桎梏,集中在三個方面爆發:
拓展性
Share nothing架構,每擴展1單位節點,需同時擴展存算資源;
每份數據至少要保存3副本,從擴展節點到完成,時間更久.
性能
Raft協議所包含的leader角色,容易造成熱點;
在性能較差的存儲下,數據庫整體性能下降會超過預期;
多種引擎各自用途不同,性能各異,無法有效應對HTAP場景。
成本
數據保存3副本,隨節點規模,成本不斷攀升,云上版本更甚;
只有高配存儲才能發揮數據庫的預期性能。
這三大難題不得不令MatrixOne團隊去思考,到底什么樣的架構才能滿足未來HTAP的需求,讓云用戶與私有化客戶,獲得最佳產品體驗與最佳實踐。如同很多破而后立的故事的開端,此時此刻恰如彼時彼刻,由CTO田豐博士引領,MatrixOne團隊開始了架構的升級之路。
三座大山,推倒重來
三大難題是舊的實驗架構的表象,如果僅僅根據表象去解決問題,無疑只能做到知其然而不知其所以然。更深層次的原因,仍然需要去被挖掘與確認,經過MatirxOne研發團隊的反復的假設與論證后,舊架構不足的根因,歸結為三個大問題,這是壓在MatrixOne之上的三座大山,如同幽靈一般,在每個MOer的頭上盤旋。
分布式框架
MatrixCube作為當時的分布式框架,提供了多副本存儲模式,每一份數據都保存3副本并且以分片(shard)形式保存,使得存儲的成本飆升。
而基于Raft選舉的Leader節點,頻繁成為了熱點,各類操作都需要通過Leader節點進行分發,在極端業務場景下,Leader節點的負載會數倍于普通節點。
引擎眾多
早期的MatrixOne內置了三種存儲引擎,三個引擎之間代碼復用率較低,使得對功能的維護需要投入更多人力。
而基于因子化算法的Plan構建方式過于激進和抽象,在計算組內部對其完全理解的程序員數量有限,往往添加功能時仍舊需要主開一人完成,新功能添加緩慢。
資源分配
舊架構采用了存算不分離的架構,這個架構導致了擴展性較差。每擴展一個單位的計算節點必須同步擴展存儲資源。
由于存儲采用了shard分片,使得在shard較大時影響了OLTP的性能,在shard較小時,又會影響OLAP性能。
在找到了三座大山之后,接下來要做的事情就是一一扳倒它們,田豐博士結合MatrixOne的產品愿景以及未來的技術趨勢,對于實驗架構進行了總結,并提出了MatrixOne獨有的架構設想,從整個架構的現狀來看,要分三步走:
第一步,將舊架構share nothing的框架破除,完成更靈活的解耦;
第二步,將多種引擎合二歸一,實現內部引擎的大一統;
第三部,重構計算引擎,留有足夠的空間給未來的產品發展。
重生后的MatrixOne

新架構通過解耦,最終實現了三個各自獨立的層級,每個層級有自己的對象單元與分工,不同類型的節點可以靈活伸縮,不再受到其他層的制約:
計算層 ,以計算節點Compute Node為單位,實現了計算和事務處理的Serverless化,又有自己的Cache,可以實現任意重啟與擴縮容;
事務層 ,以數據庫節點Database Node為與日志節點Log Service為單位,提供完整的日志服務以及元數據信息,內置Logtail用于保存最近數據;
存儲層 ,全量數據保存在以S3為代表的對象存儲中,實現了低成本的無線伸縮存儲方式,以File Service命名的統一文件操作服務,實現了不同節點對底層存儲的無感知操作。

在確定了以TAE作為唯一存儲引擎之后,對融合后的TAE引擎又做了諸多設計上的調整,才有了后來融合后的TAE存儲引擎。完成了單一引擎完成所有數據庫存儲行為的目標,并且具備了如下優勢:
列存管理 ,統一的列存與壓縮,對于OLAP業務有著先天的性能優勢;
事務處理 ,共享日志與DN節點共同完成對計算節點的事務支持;
冷熱分離 ,使用File Service以S3對象存儲作為目標,每個計算節點都有自己的Cache。
多次運行測試,得出置信度較高的結果:

早期的計算引擎中,兼容MySQL的大目標沒有變化,但是對于節點調度、執行計劃、SQL能力又有著更高的要求。重構后的高性能計算引擎,既具備了實驗架構中計算引擎的MPP,又彌補了過去的諸多不足:
兼容MySQL ,既有對MySQL協議的支持,又包含了對MySQL語法的支持;
融合引擎 ,基于DAG重新構建執行計劃,可以同時執行TP和AP;
節點調度 ,未來可支持自適應節點內和節點間調度,同時滿足并發和并行執行;
完善SQL能力,支持子查詢、窗口函數、CTE、Spill內存溢出處理等。
積跬步以至千里
回顧歷時數月的架構升級之路,充滿了各種辛酸和痛苦。無論考慮的多么充分,在實際開發中,總會遇到各種各樣意想不到的問題出現,尤其是在一些關鍵問題上的困難,讓研發團隊從開始的一籌莫展,到偶爾的靈光乍現,再到很后面的零之曙光,走向最終的黎明時刻。個中三昧,不言而喻。
這些難題中,主要圍繞在存儲、事務、負載隔離與資源配比幾個方面。
尋找更合適的存儲
在意識到三副本存儲帶來的問題后,如何尋找一個新的存儲適配新架構,成為了當時一大難題,而這個新的存儲必須滿足兩個核心需求,低成本與冷熱數據分離。
在對市面上的諸多存儲進行了調研以及試驗之后,AWS S3成為了最終的選擇。單一副本,自帶的冷熱數據分離。
事務分工的調整
最初的新架構中,計算節點CN與數據庫節點DN之間的分工是CN負責計算,計算結果推給DN,由DN完成事務。隨著開發進度的不斷推進,這個分工開始出現了問題,DN對事務的處理能力成為整個系統的瓶頸。因此,對于CN和DN的分工,必須做重新定義:
CN負責所有的計算以及事務邏輯,DN負責保存元數據信息、日志信息以及事務裁決,DN不再成為瓶頸;
在日志中引入Logtail對象,用于保存最近日志中的關聯數據,定期將Logtail的數據寫入S3中,CN擴容可以實時將Logtail數據同步至Cache,實現了部分數據共享;
為事務大小設置閾值,超過閾值上限的事務直接寫S3,日志只保存記錄寫入記錄,未超過閾值的事務繼續由DN寫入,極大增加了吞吐量。
實現HTAP的工作負載隔離
作為HTAP數據庫,如何實現不同類型的工作負載隔離,是一個必須解決的問題。在完成了對舊的實驗架構的靈活解耦之后,工作負載的隔離也得以實現:
服務器級別的隔離,硬件資源充裕的情況下,各個組件分別在不同的物理機運行,接入同一個對象存儲;
容器級別的隔離,硬件資源有限的情況下,利用所有節點無狀態的特性,以容器作為各個節點的隔離手段。
實現資源配比的靈活調整
作為HTAP數據庫,日常業務中,不同業務場景的比例是在動態變化中,對于資源的配比也有著更高的要求,而舊架構下的資源分配模式注定無法實現靈活調整,需要對各個節點實現更加精細化的管理,包含但不限于:
CN節點的分工,允許用戶對CN進行劃分,用于TP或AP業務,其中某項業務資源出現瓶頸之后,對CN進行水平擴容;
在不類業務的CN組之間,動態判斷各組的負載情況,當前兩類業務的負載差異較大時,可以自動將閑置資源分配至繁忙組內;
通過租戶(account)的邏輯概念,實現邏輯資源的完全隔離,不同的租戶可以以獨享或共享的方式使用指定的CN資源。
復盤收獲
在諸多問題得以解決的背后,是眾多MOer一次次發起的攻堅,在陣痛之后,也收獲了很多過去不曾涉足過的知識與經驗。這些不僅僅是解決問題的積累,同樣也為今后MatrixOne的開發積累了一比寶貴的財富。
為此我從解耦之后的三層架構角度,對相關幾位同事做了訪談,在傾聽了他們對問題的回顧與思考之后,做出了如下的反饋:
計算層
理解SQL的執行,通過重構Plan,對于SQL語法的解析、執行計劃以及SQL標準語法都有了更多認識;
事務與ACID,專注于單一引擎之后,幾乎每一條SQL都要考慮事務與ACID,需要對這些有更深的理解。
事務層
CN與DN的適配,從架構升級開始,CN與DN的分工與適配成為了巨大難題,反復驗證中得到了最優解;
部分數據共享,Logtail的引入,實現了某一部分數據在不同CN之間共享。
存儲層
使用S3存儲,積累了基于S3等對象存儲的引擎開發經驗,原來對象存儲也可以很好地適配數據庫;
Fileservice,一種存儲服務,去實現不同節點不同底層存儲類型的讀寫,是個極大的挑戰。
總結
矩陣起源公司成立于2021年,在上海、深圳、北京、硅谷等城市設有分支機構。團隊成員由各領域專家組成,在分布式基礎架構、數據庫、大數據及人工智能領域經驗豐富。致力于成為行業領先的數據基礎軟件公司,幫助所有企業和用戶簡單、敏捷、高效地擁抱數據價值。
整個MatrixOne的架構升級之路,始于0.4迭代,在0.6迭代初步完成,歷時半年多,數十位一線研發與測試工程師投入其中。刪掉了關聯的幾十萬行代碼,又新增了體量更多的新代碼。最終完成了從share nothing的newSQL架構到今天的新分布式HTAP架構,團隊與產品共同獲得了成長。
最后,讓我們總結一下MatrixOne架構升級的關鍵點:
從存算一體到計算、事務、存儲三層解耦
從多引擎到單一TAE的HTAP融合引擎
從因子化算法到DAG的計劃構建
從多副本存儲到對象存儲與Logtail的引入
靈活調整節點分配帶來的資源隔離