大數據

OceanBase 數據庫源碼解讀之模塊結構

竹翁,OceanBase 內核研發總監

楊志豐,花名竹翁,畢業於北京大學,長期從事分佈式系統和數據庫的研發工作,現於阿里巴巴/螞蟻金服自主研發的分佈式關係數據庫 OceanBase 團隊負責研發工作,致力於把設計先進的 HTAP 數據庫系統打造成技術業內標杆的核心基礎設施。在 OceanBase 系統中,他先後負責研究 OceanBase 的 SQL 引擎、分佈式主控模塊、多模數據庫方向以及 OceanBase 的數據庫平臺產品研發,並於近期開始負責內核創新研發工作。竹翁對 C++、分佈式系統原理、SQL 查詢處理、事務處理、編譯技術、工程效率等方面具有深入的理解。

引言

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

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

一、數據庫的整體架構:梳理 OceanBase 數據庫代碼的整體架構和模塊構成,以及各模塊的各自功能。

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

三、分區的一生:講解 OceanBase 數據庫存儲層的相關知識。

四、事務的一生:解析 OceanBase 數據庫事務的外部接口。

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

六、虛擬表:拆解 OceanBase 數據庫虛擬表的本質。

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

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

 

正文

本文為《帶你讀源碼系列》第一篇,主要為大家介紹 OceanBase 數據庫代碼的整體架構和模塊構成,以及各模塊的功能。

 

頂層目錄

1.jpg

上圖為頂層目錄。主體代碼在 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 目錄

2.jpg

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

oblib 目錄

3.jpgimage.gif

一般情況下,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 表示一個包含類型信息的值。比如新增列類型就要改這個類。

4.jpg

接下來重點介紹 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 目錄

5.jpg

終於輪到了 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 源碼的目錄架構做了一個整體概述,後續將會對具體內容進行層層拆解,希望對大家有所幫助。

 

在閱讀過程中,如果您有任何疑問,可以通過以下方式與我們進行交流:

釘釘群:33254054

6.jpg

釘釘掃碼入群

github:https://github.com/oceanbase/oceanbase

博客問答:https://open.oceanbase.com/answer

gitee:https://gitee.com/oceanbase

Leave a Reply

Your email address will not be published. Required fields are marked *