1. 程式人生 > 其它 >OceanBase 資料庫原始碼解讀之模組結構

OceanBase 資料庫原始碼解讀之模組結構

引言

在資料庫 OceanBase 3.0 峰會上,OceanBase 宣佈正式開源,併成立 OceanBase 開源社群, 300 萬行核心程式碼向社群開放。開源的 OceanBase 社群版程式碼由於經過多年的迭代與變化,新人上手殊為不易。為了幫助大家理清頭緒愉快上手,本人將利用碎片時間圍繞“原始碼解讀”寫個系列介紹。將通過一系列文章進行闡述,幫您理清資料庫的內在本質。

本系列將從以下六大模組進行介紹:

一、資料庫的整體架構:梳理 OceanBase 資料庫程式碼的整體架構和模組構成,以及各模組的各自功能。

二、SQL 的一生:介紹 OceanBase 資料庫中任意一條 SQL 的執行流程,包括接收、處理、返回結果給客戶端的過程。

三、分割槽的一生:講解 OceanBase 資料庫儲存層的相關知識。

四、事務的一生:解析 OceanBase 資料庫事務的外部介面。

五、租戶的一生:闡述 OceanBase 資料庫多租戶的特性。

六、虛擬表:拆解 OceanBase 資料庫虛擬表的本質。

(注:各位看官,本系列是程式碼導讀,不是設計解讀,一定要結合程式碼來看,並且最好配上動手實踐,否則就是把輔導手冊當教材看了。)

通過本系列的原始碼解讀文章,您首先可以瞭解 OceanBase 資料庫的基本原理,輕鬆 get 資料庫的實現步驟。推而廣之,您也可以把 OceanBase 的實現原理應用到其他資料庫,這對您學習其他的資料庫也將帶來幫助。其次,在熟悉了 OceanBase 的程式碼之後,如果有需要,您可以直接在後續工作中使用我們的程式碼,或者為 OceanBase 社群貢獻您的程式碼。

正文

本文為《帶你讀原始碼系列》第一篇,主要為大家介紹 OceanBase 資料庫程式碼的整體架構和模組構成,以及各模組的功能。

頂層目錄

上圖為頂層目錄。主體程式碼在 src 目錄下,單元測試程式碼在 unittest 目錄下。unittest 目錄下單測的目錄結構與 src 目錄下的結構和命名方式相同。例如,src/sql/abc.cpp 對應的單測檔案是 unittest/sql/test_abc.cpp,單測使用 gtest 和 gmock 框架。unittest 目錄下也包含一些重要元件的整合測試。

test 目錄下則是系統測試,這裡的測試物件是完整啟動的 observer。其中 test/mysql_test 目錄下包含的各種測試用例是利用修改後的 mysql_test 框架執行的測試用例。它主要用 SQL 來測試系統功能正確性。

cmake 目錄和 build.sh 指令碼編譯相關,我們將在以後的文章中詳細介紹。

deps 目錄

deps 目錄比較特別,它包含 src 所依賴的東西。deps/3rd 目錄包含一組工具,用來下載和編譯第三方庫,專門為社群版研製。deps/easy 是阿里的多隆大神早年間開發的一個基於 libev 的 rpc 框架,我們在此基礎上做了一些修改。現在隨著 OceanBase 的開源,OceanBase 的 rpc 框架是基於 easy 的。deps/oblib 是最核心的基礎庫。為什麼放到這裡呢?因為它經過多次與 OceanBase 程式碼倉庫的分分合合。

oblib 目錄

一般情況下,oblib 庫不依賴於 OceanBase src,只被依賴。rpc 是 OceanBase 業務程式碼所使用的內部 rpc 框架,它依賴於 libeasy;rpc模組也提供了一組方便的巨集來快捷定義 rpc。lib 目錄是依賴的最底層,它沒有外部依賴,包含了錯誤碼定義、容器類、記憶體分配器等大量基礎類,以及最基礎的標頭檔案 ob_define.h(想喝咖啡時你可以改一下這個檔案然後執行 make進行編譯)。一般情況下,oblib 目錄下的程式碼,特別是 oblib/src/lib 下的程式碼是與 OceanBase 業務程式碼無關的。也就是說,如果你在做一個其他的 C++ 專案,也可以直接使用這個庫。注意,OceanBase 的編碼規範要求不使用 STL 容器,所以這裡有大量的“輪子”。common 目錄下的程式碼依賴於 lib,但是比頂層 src 又更業務無關一些。如果你做一個儲存系統(即使不是資料庫),可能用的到這裡的公共類。這裡面最重要的類是 ob_object.h 中的 ObObj 表示一個包含型別資訊的值。比如新增列型別就要改這個類。

接下來重點介紹 deps/oblib/src/common 目錄下的幾個子目錄。object 目錄下是最重要的資料型別 ObObj 的定義,OceanBase 支援的列資料型別,這從列舉型別 ObObjType 中可以看出來。可以看出 36 以後是 Oracle 租戶型別下的資料型別。ObObj 是儲存和資料處理的“原子”。rowkey 目錄下定義的 ObRowkey 是每一行記錄的主鍵。OceanBase 在底層儲存只有索引組織表,每一行必須有主鍵;使用者可見的無主鍵表是通過一個隱藏的自增列做 rowkey 的,算是一個模擬。儲存引擎的 memtable 和 sstable 中都是用 rowkey 索引的。row 目錄下定義了一行記錄的表示 ObNewRow (你找不到ObRow:),他是資料處理的“分子”,基於它定義的 ObRowIterator 是很多操作類的介面。

log 目錄定義了一組很好用的日誌巨集。OceanBase 程式碼裡面到處都有的 LOG_WARN 等巨集就是在 ob_log.h 提供的。它的介面綜合了 printf 和 cout 的優點,沒有 cout 那麼簡約,又是強型別的,且限定了統一的 key-value 風格。為了在 C++ 老版實現這組介面,我們用了很多模板和巨集的絕妙小技巧。如果你先熟悉這組介面,再嘗試貢獻程式碼,你會愛上他們。

src 目錄

終於輪到了 src 目錄。

election 是分散式選舉模組,它是比較獨立的,因為在執行時如果選舉不出 1 號 leader,系統所有元件就都不工作。它獨立於 Paxos 協議。該選舉協議要求各節點時鐘同步。clog 最初的意思是 commitlog,現在成了專有詞彙,特指 OceanBase 的事務 redo 日誌。Paxos 的實現也在這個目錄下。archive 是日誌歸檔元件,備份恢復依賴該元件。

rootserver 目錄是 OceanBase 叢集總控服務。這個命名不夠準確,準確的名字應該是 rootservice,它不是獨立程序,而是某些 observer 內部啟動的一組服務,感興趣的讀者可以看看 OceanBase 0.4 的開原始碼。叢集管理和自動容災、系統自舉、分割槽副本管理和負載均衡,以及 DDL 的執行都在這個元件中。

share 目錄是被強行從“母體”oblib/src/common 中剝離出來的公共類,所以它們的 namespace 是 common 而不是 share。

sql 就是 SQL。storage 就是儲存引擎。事務管理位於 storage/transaction 下。

observer 是所有元件的“總裝車間”,入口是 ob_server.h 和 ob_service.h。MySQL 協議層的命令處理入口位於 observer/mysql。

結語

資料庫的原始碼內容博大精深。本文對 OceanBase 原始碼的目錄架構做了一個整體概述,後續將會對具體內容進行層層拆解,希望對大家有所幫助。