天天看點

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 資料庫代碼的整體架構和子產品構成,以及各子產品的功能。

頂層目錄

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 目錄

OceanBase 資料庫源碼解讀之子產品結構

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

oblib 目錄

OceanBase 資料庫源碼解讀之子產品結構
OceanBase 資料庫源碼解讀之子產品結構

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

OceanBase 資料庫源碼解讀之子產品結構

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

OceanBase 資料庫源碼解讀之子產品結構

終于輪到了 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

OceanBase 資料庫源碼解讀之子產品結構

釘釘掃碼入群

github:

https://github.com/oceanbase/oceanbase

部落格問答:

https://open.oceanbase.com/answer

gitee:

https://gitee.com/oceanbase