TiDB 源碼閱讀系列文章(二)源碼架構介紹
來自專欄 DB Notes
第一篇文章介紹整體的架構,知道 TiDB 有哪些模塊,分別是做什麼的,從哪裡入手比較好,哪些可以忽略,哪些需要仔細閱讀。
這篇文章是一篇入門文檔,難度係數比較低,其中部分內容可能大家在其他渠道已經看過,不過為了內容完整性,我還是會放在這裡。
TiDB 架構
本次 TiDB 源碼之旅從這幅簡單的架構圖開始,這幅圖很多人都看過,我們可以用一句話來描述這個圖:『TiDB 是一個支持 MySQL 協議,以某種支持事務的分散式 KV 存儲引擎為底層存儲的 SQL 引擎』。從這句話可以看出有三個重要的事情,第一是如何支持 MySQL 協議,與 Client 交互,第二是如何與底層的存儲引擎打交道,存取數據,第三是如何實現 SQL 的功能。本篇文章會先介紹一些 TiDB 有哪些模塊及其功能簡要介紹,然後以這三點為線索,將這些模塊串聯起來。
代碼簡介
TiDB 源碼完全託管在 Github 上,從項目主頁可以看到所有信息。整個項目使用 Go 語言開發,按照功能模塊分了很多 Package,通過一些依賴分析工具,可以看到項目內部包之間的依賴關係。
大部分包都以介面的形式對外提供服務,大部分功能也都集中在某個包中,不過有一些包提供了非常基礎的功能,會被很多包依賴,這些包需要特別注意。
項目的 main 文件在 tidb-server/main.go,這裡面定義了服務如何啟動。整個項目的 Build 方法可以在 Makefile 中找到。
除了代碼之外,還有很多測試用例,可以在 xx_test.go 中找到。另外 cmd 目錄下面還有幾個工具包,用來做性能測試或者是構造測試數據,其中的 benchkv 以及 benchraw 可以當做 TiKV 的 go client 使用示例。
模塊介紹
從哪裡入手
粗看一下 TiDB 有 80 個包,讓人覺得無從下手,不過並不是所有的包都很重要,另外一些功能只會涉及到少量包,從哪裡入手去看源碼取決於看源碼的目的。
如果是想了解某一個具體的功能的實現細節,那麼可以參考上面的模塊簡介,找到對應的模塊即可。
如果是相對源碼有全面的了解,那麼可以從 tidb-server/main.go 入手,看 tidb-server 是如何啟動,如何等待並處理用戶請求。再跟著代碼一直走,看 SQL 的具體執行過程。另外一些重要的模塊,需要看一下,知道是如何實現的。輔助性的模塊,可以選擇性的看一下,有大致的印象即可。
重要模塊
在全部 80 個模塊中,下面幾個模塊是最重要的,希望大家能仔細閱讀,針對這些模塊,我們也會用專門的文章來講解。
- plan
- expression
- executor
- distsql
- store/tikv
- ddl
- tablecodec
- server
- types
- kv
- session
輔助模塊
除了重要的模塊之外,餘下的是輔助模塊,但並不是說這些模塊不重要,只是鎖這些模塊並不在 SQL 執行的關鍵路徑上,我們也會用一定的篇幅描述其中的大部分包。
SQL 層架構
這幅圖比上一幅圖詳細很多,大體描述了 SQL 核心模塊,大家可以從左邊開始,順著箭頭的方向看。
Protocol Layer
最左邊是 TiDB 的 Protocol Layer,這裡是與 Client 交互的介面,目前 TiDB 只支持 MySQL 協議,相關的代碼都在 server 包中。
這一層的主要功能是管理客戶端 connection,解析 MySQL 命令並返回執行結果。具體的實現是按照 MySQL 協議實現,具體的協議可以參考 MySQL 協議文檔。這個模塊我們認為是當前實現最好的一個 MySQL 協議組件,如果大家的項目中需要用到 MySQL 協議解析、處理的功能,可以參考或引用這個模塊。
連接建立的邏輯在 server.go 的 Run() 方法中,主要是下面兩行:
236: conn, err := s.listener.Accept()
258: go s.onConn(conn)
單個 Session 處理命令的入口方法是調用 clientConn 類的 dispatch 方法,這裡會解析協議並轉給不同的處理函數。
SQL Layer
大體上講,一條 SQL 語句需要經過,語法解析-->合法性驗證-->制定查詢計劃-->優化查詢計劃-->根據計劃生成查詢器-->執行並返回結果 等一系列流程。這個主幹對應於 TiDB 的下列包:
KV API Layer
TiDB 依賴於底層的存儲引擎提供數據的存取功能,但是並不是依賴於特定的存儲引擎(比如 TiKV),而是對存儲引擎提出一些要求,滿足這些要求的引擎都能使用(其中 TiKV 是最合適的一款)。
最基本的要求是『帶事務的 Key-Value 引擎,且提供 Go 語言的 Driver』,再高級一點的要求是『支持分散式計算介面』,這樣 TiDB 可以把一些計算請求下推到 存儲引擎上進行。
這些要求都可以在 kv 這個包的[介面]中找到,存儲引擎需要提供實現了這些介面的 Go 語言 Driver,然後 TiDB 利用這些介面操作底層數據。
對於最基本的要求,可以重點看這幾個介面:
- Transaction:事務基本操作
- Retriever:讀取數據的介面
- Mutator:修改數據的介面
- Storage:Driver 提供的基本功能
- Snapshot:在數據 Snapshot 上面的操作
- Iterator:Seek 返回的結果,可以用於遍曆數據
- 有了上面這些介面,可以對數據做各種所需要的操作,完成全部 SQL 功能,但是為了更高效的進行運算,我們還定義了一個高級計算介面,可以關注這三個 Interfce/struct :
- Client:向下層發送請求以及獲取下層存儲引擎的計算能力
- Request: 請求的內容
- Response: 返回結果的抽象
小結
至此,讀者已經來了解了 TiDB 的源碼結構以及三個主要部分的架構,更詳細的內容會在後面的章節中詳細描述。
推薦閱讀:
※TiDB RC4 Release
※TiDB 在零氪科技(LinkDoc)大數據醫療系統的實踐
※TiDB 1.1 Beta Release
※oceanbase、TiDB這類NewSQL最近勢頭好強勁,它們的定位究竟是什麼?
※TiDB能否覆蓋HBase的絕大多數使用場景?