Databend 源碼閱讀系列(一): 開篇
前言
Databend 在 2021 年開源后,陸續(xù)受到了很多社區(qū)同學(xué)的關(guān)注。Databend 使用了 Rust 編程語言。為了吸引更多的開發(fā)者,特別是沒有 Rust 開發(fā)經(jīng)驗的新同志,我們設(shè)計了 Rust 相關(guān)課程,同時建立了多個 Rust 興趣小組。
Databend 在 issue 中還引入了“Good First issue”的 label 來引導(dǎo)社區(qū)新同學(xué)參與第一次貢獻(xiàn),目共有超過一百多位 contributors,算是一個不錯的成果。但 Databend 也在過去的一年中經(jīng)歷了數(shù)次迭代,代碼日漸復(fù)雜。目前代碼主干分支有 26 w 行 rust 代碼,46 個 crate,對于新接觸 Databend 的技術(shù)愛好者來說,貢獻(xiàn)門檻越來越高。即使是熟悉 rust 的同學(xué),clone 代碼后,面對著茫茫碼海,竟不知如何讀起。在多個社區(qū)群中,也有朋友數(shù)次提到什么時候能有一個 Databend 源碼閱讀系列文章,幫助大家更快熟悉 Databend 代碼。
因此,我們接下來會開展“Databend?源碼閱讀”系列文章,主要受眾是社區(qū)技術(shù)開發(fā)者,希望通過源碼閱讀,來加強和社區(qū)的技術(shù)交流,引發(fā)更多思維碰撞。Databend 的故事
Databend 的故事
很多同學(xué)都問過我們一個問題:為什么你們要用 Rust 從零構(gòu)建一個數(shù)據(jù)庫?其實這個問題可以分為兩個子問題:
1.為什么選擇的是 Rust?
答:我們早期的成員大多是 ClickHouse、tidb 、tokudb 等知名數(shù)據(jù)庫的貢獻(xiàn)者,從技術(shù)棧來說更熟悉的是 C++ 和 Go。虎哥@bohutang 在疫情期間也使用 Go 實現(xiàn)了一個小的數(shù)據(jù)庫原型 vectorsql(https://github.com/vectorengine/vectorsql),有同學(xué)表示 vectorsql 的架構(gòu)非常優(yōu)雅,值得學(xué)習(xí)借鑒。

語言本沒有孰劣之分,要從面向的場景來聊聊。目前大多的 DMBS 使用的是 C++/Java,新型的 NewSQL 更多使用的是 Go。在以往的開發(fā)經(jīng)驗來看,C/C++ 已經(jīng)是高性能的代名詞,開發(fā)者更容易寫出高運行效率的代碼,但 C++ 的開發(fā)效率實在不忍直視,工具鏈不是很完善,開發(fā)者很難一次性寫出內(nèi)存安全,并發(fā)安全的代碼。而 Go 可能是另外一個極端,大道至簡,工具鏈完善,開發(fā)效率非常高,不足之處在于泛型的進(jìn)度太慢了,在 DB 系統(tǒng)上內(nèi)存不能很靈活的控制,且難于達(dá)到前者的運行性能,尤其使用 SIMD 指令還需要和匯編代碼交互等。我們需要的是兼具 開發(fā)效率(內(nèi)存安全,并發(fā)安全,工具鏈完善)& 運行效率 的語言,當(dāng)時看來,Rust 可能是我們唯一的選擇了,歷經(jīng)嘗試后,我們也發(fā)現(xiàn),Rust 不僅能滿足我們的需求,而且很酷!
2.為什么要從零構(gòu)建一個數(shù)據(jù)庫系統(tǒng)?
總體來說,路線無非就以下兩條:
基于知名的開源數(shù)據(jù)庫做二次開發(fā)優(yōu)化
這條路線可能更多人會選擇,因為有一個好的數(shù)據(jù)庫底座,無需再做一些重復(fù)性的工作,在上面做二次開發(fā)的話能省不少力氣,團(tuán)隊專注做優(yōu)化改進(jìn)重構(gòu),能更早推動版本,落地商業(yè)化。缺點是 fork 后的版本難于再次回饋到社區(qū),相當(dāng)于另外一套獨立的系統(tǒng),如 PG 下的各個子流派。
從零構(gòu)建一套新的數(shù)據(jù)庫系統(tǒng)
這條路線走起來比較艱難,因為數(shù)據(jù)庫系統(tǒng)實在太龐大了,一個子方向都足夠?qū)I(yè)人士深入研究十幾年。這個方向雖然沒能直接站在已有的底座上,但會讓設(shè)計者更加靈活可控,無需關(guān)注太多歷史的包袱。Databend 在設(shè)計之初面向的是云原生數(shù)倉的場景,和傳統(tǒng)的數(shù)據(jù)庫系統(tǒng)有很大的區(qū)別,如果基于傳統(tǒng)數(shù)據(jù)庫系統(tǒng)來做,改造代碼的成本和從零做的成本可能差不多,因此我們選擇的是這條路來從零打造一個全新的云數(shù)倉。
Databend 的架構(gòu)
畫虎畫皮難畫骨,我們先從 Databend 的“骨”聊起

雖然我們是使用 Rust 從零開始實現(xiàn)的,但不是完全閉門造輪子,一些優(yōu)秀的開源組件或者生態(tài)也有在其中集成。如:我們兼容了 Ansi-SQL 標(biāo)準(zhǔn),提供了 MySQL/ClickHouse 等主流協(xié)議的支持,擁抱了萬物互聯(lián)的 Arrow 生態(tài),存儲格式基于大數(shù)據(jù)主流的 Parquet 格式等。我們不僅會積極地回饋了貢獻(xiàn)給上游,如 Arrow2/Tokio 等開源庫,一些通用的組件我們也抽成獨立的項目開源在Github(openraft, opendal, opencache, opensrv?等)。
Databend 定義為云原生的彈性數(shù)據(jù)庫,在設(shè)計之初我們不僅要做到計算存儲分離,每一層的極致的彈性都是設(shè)計主要考量點。Databend 主要分為三層:MetaService Layer,Query Layer,Storage Layer,這三層都是可以彈性擴(kuò)展的,意味著用戶可以為自己的業(yè)務(wù)選擇最適合的集群規(guī)模,并且隨著業(yè)務(wù)發(fā)展來伸縮集群。
下面我們將從這三層來介紹下 Databend 的主要代碼模塊
Databend 的模塊
MetaService Layer
MetaService 主要用于存儲讀取持久化的元數(shù)據(jù)信息,比如 Catalogs/Users 等。

Query Layer
Query 節(jié)點主要用于計算,多個 query 節(jié)點可以組成 MPP 集群,理論上性能會隨著 query 節(jié)點數(shù)水平擴(kuò)展。SQL 在 query 中會經(jīng)歷以下幾個轉(zhuǎn)換過程

從 SQL 字符串經(jīng)過 Parser 解析成 AST 語法樹,然后經(jīng)過 Binder 綁定 catalog 等信息轉(zhuǎn)成邏輯計劃,再經(jīng)過一系列優(yōu)化器處理轉(zhuǎn)成物理計劃,最后遍歷物理計劃構(gòu)建對應(yīng)的執(zhí)行邏輯。query 涉及的模塊有:

Storage Layer
Storage 主要涉及表的 Snapshots,Segments 以及索引信息等管理,以及和底層 IO 的交互。Storage 目前一大亮點是基于 Snapshot 隔離 實現(xiàn)了類似 Iceberge 方式的 Increment view, ?我們可以對表在任意歷史狀態(tài)下進(jìn)行 time travel 訪問。后續(xù)規(guī)劃
后續(xù)規(guī)劃
源碼閱讀系列剛剛開始撰寫,后續(xù)預(yù)計將按照介紹各個模塊的方式進(jìn)行逐步講解,輸出主要以文章為主,一些比較重要且有趣的模塊設(shè)計可能會以視頻直播的方式和大家一起交流。
目前只是一個初步的規(guī)劃,在這個過程中會接受大家的建議做一些時間內(nèi)容調(diào)整。無論如何,我們都期待通過這個系列的活動,讓更多志同道合的人參與到 Databend 的開發(fā)中來,一起學(xué)習(xí)交流成長。
關(guān)于 Databend
Databend 是一款開源、彈性、低成本,基于對象存儲也可以做實時分析的新式數(shù)倉。期待您的關(guān)注,一起探索云原生數(shù)倉解決方案,打造新一代開源 Data Cloud。
Databend 文檔:https://databend.rs/
Twitter:https://twitter.com/Datafuse_Labs
Slack:https://datafusecloud.slack.com/
Wechat:Databend
GitHub :https://github.com/datafuselabs/databend
