導讀前端
與傳統關係型數據庫相比,分佈式數據庫系統具備多集羣、多節點、高併發等特性,這就須要分佈式數據庫的 SQL 引擎可以在知足用戶常規的 SQL 請求之外,提供多集羣、多節點協同計算的能力,從而提升查詢效率。本文將介紹分佈式數據庫 ZNBase 的 SQL 引擎架構特色,以及其中各大服務組件的技術原理與工做流程。node
分佈式數據庫架構
目前業界最流行的分佈式數據庫主要分爲兩種架構。一種是以 Google Spanner 爲表明的 Shared nothing 架構,另外一種是以 AWS Auraro 爲表明的計算/存儲分離架構。 git
Spanner 是 shared nothing 的架構,內部維護了自動分片、分佈式事務、彈性擴展能力,數據存儲仍是須要 sharding,plan 計算也須要涉及多臺機器,也就涉及了分佈式計算和分佈式事務。 數據庫
Auraro 主要思想是計算和存儲分離架構,使用共享存儲技術,這樣就提升了容災和總容量的擴展。可是在協議層,只要是不涉及到存儲的部分,本質仍是單機實例的 SQL 引擎,不涉及分佈式存儲和分佈式計算,這樣就和傳統數據庫兼容性很是高。緩存
浪潮云溪 NewSQL 數據庫 ZNBase 完美地繼承了 Spanner 的設計理念,實現了基於對等架構的分佈式 SQL 引擎。數據結構
ZNBase 的 SQL 引擎
ZNBase 的 SQL 引擎在傳統的 SQL 引擎基礎上,引入了分佈式的概念,經過多個集羣節點協同計算更高效的執行用戶 SQL 查詢,整體架構圖以下:架構
SQL 引擎靜態結構,包含五大服務併發
集羣中每一個節點 node 都獨有鏈接服務(Connectivity Service)、編譯服務(Compile Service) 和緩存服務(Cache Service)三大服務,能夠完成用戶的 SQL 查詢執行的前端準備工做。框架
同時,全部節點又共同組成了分佈式的目錄服務(Distibuted Catalog Service)和分佈式的執行服務(Distibuted Execute Service),經過這兩個服務完成了多個 node 節點的協同執行,提升了分佈式 SQL 引擎的執行性能。最終將結構化數據,轉化爲底層存儲可識別的 KV 編碼對,經過 Batch 批處理髮送到事務層進行處理。異步
SQL 引擎執行流程
下文將對這五大服務進行展開介紹。
1.鏈接服務 Connectivity Service
分佈式數據庫 ZNBase 採用的是對等架構,集羣中的任意節點均可以做爲接入節點。同時,ZNBase 支持 PostgreSQL 協議,SQL 查詢能夠經過各類支持 PostgreSQL 協議的驅動發送到集羣。
鏈接服務流程以下:
- 用戶經過後臺守護進程進行鏈接器管理,爲每一個客戶端構建新的 Executor。
- 當用戶從客戶端發起指令後,從客戶端接收和解包流。
- 執行完畢後,將操做結果打包返回給客戶端。
- 用戶的每一次操做,都被認爲是一個單獨的事務操做。
2.分佈式目錄服務 Dist Catalog Service
ZNBase 的 Dist Catalog Service 不只實現了傳統關係數據庫的 schema metadata,包含了經常使用的庫、表、列、模式等數據庫元數據,並且實現了元數據信息的高可用,以及分佈式訪問。元數據採用多副本存儲、分佈式存儲,保證少於一半數據不可用的狀況下,元數據信息仍然可用。並且每一個對等節點在啓動時會直接內存化元數據路由表的第一級 Root Meta Range 數據,保證任意節點都能訪問到須要的元數據信息。
Catalog 信息發生變化時,首先會更新到元數據存儲的寫入節點,經過 Raft 協議同步到多副本。同時使得各個節點的 Catalog 緩存失效,在使用時進行異步的更新,保證各節點數據的一致性。
3.編譯服務 Compile Service
ZNBase 的編譯服務包括了 SQL 前端和 SQL 中端功能,SQL 前端實現了傳統數據庫的 Scanner、Parser、SQL 語法、SQL 語義以及數據庫對象和權限校驗的處理,生成了 AST(抽象語法樹)。
SQL 中端實現了數據庫的優化器的功能。優化器負責給執行引擎提供輸入,它接收來自 SQL 前端解析好的 AST 樹,而後須要從全部可能的計劃中選擇代價最優的計劃提供給執行引擎。
ZNBase 的優化器是基於 Cascades 論文實現的搜索框架。從數據庫的發展歷程來看,基於 Cascades 的搜索框架已經成爲了業界標準,包括商業數據庫 SQL Server 以及開源數據庫 GP/ORCA 都採用 Cascades 實現。編譯服務的總體架構以下:
SQL 引擎編譯服務結構圖
如上圖所示,Client 端輸入的 SQL 語句經過 go-yacc 層的詞法、語法、語意義解析爲 AST 語法樹,通過 Memo construction 轉換爲 CBO 初始的 Memo 樹。Memo 由一些列等價的 group 組成,每一個 group 表示一個邏輯等價表達式集合,Memo 自己是樹狀結構化的,能夠表明查詢語句,可是又不包含大量的元數據信息,能夠被緩存以提升執行效率,這點在 Cache Service 中會給出解析。構造好的 Memo 直接應用於基本的 RBO 轉換。以後,Memo 數據根據統計信息通過 CBO 優化(等價發掘和最優化Cost)選擇轉換爲最優路徑的計劃。
RBO 根據指定的優先順序規則,對指定的表進行執行計劃的選擇。好比在規則中:索引的優先級大於全表掃描。
當某些 SQL 語句的寫法並不利於快速從存儲中查詢數據的場景下,RBO 會對其進行相應轉化,例:
SELECT * FROM t1 ,t2 WHERE t1.a > 4 AND t2.b >5;
若是先進行笛卡爾積再進行過濾條件時,則會產生不少沒必要要的元組。可是若是先過濾 t1 , t2 的關係,在進行笛卡爾積,那麼表達式的消耗將大大減小。在進行過濾時,能作到一個select算子中就作到算子中,不能的話,就在具備過濾須要的列時及時作好,好比 a.a > 5 and b.b > 10 and a.c > a.b,第一個和第二個條件均可以推到 select 算子中,在這兩個算子上面當即加一個 a.c > a.b 的過濾條件。
CBO 則基於統計信息對代價進行代價預估,獲得一條較優的查詢路徑。例如:咱們在作三個錶鏈接的時候,若是有統計信息的話,咱們就能夠知道,哪兩個表先作鏈接會使接下來執行的代價更小,由於在作 hashjoin 時,咱們總但願小的表先進入,而後製做成一個小的 hashtable,由於 hashtable 比較小,因此以後的大表在作 join 的時候,就會有更高的命中率。
4.緩存服務 Cache Service
ZNBase 提供了兩種類型的緩存服務,主要是用來提升數據訪問效率,減小重複消耗。
第一種是 Session 級的 Querycache,主要是緩存用戶 SQL 語句指紋對應的 Memo 樹數據結構,減小同一 Session 的 SQL 語句屢次構建邏輯計劃的開銷。SQL 語句指紋含有 SQL 語句的相關 Catalog 信息和權限等校驗信息。
在重用 Memo 以前,會對 Memo 是否過時進行檢查:解析元數據所依賴的每一個數據源和 schema,以便檢查徹底限定的對象名是否仍解析爲相同對象的相同版本,檢查和時間相關的類型的構造和比較方式,以及用戶是否仍有足夠的權限訪問這些對象。若是依賴項再也不是最新的,則斷定該 Memo 過時,須要從新構建。
第二種是集羣級別的元數據相關 Cache。其中 Catalog 信息包含了數據庫經常使用的 scheme 信息和元數據路由信息。元數據路由信息由 Dist Catalog service 提供。經過元數據路由信息集羣任意節點能夠訪問到全部須要的元數據或者數據。
5.分佈式執行服務 Dist Execution Service
ZNBase 的 SQL 引擎總體設計模型參考了 Volcano 模型[1],Volcano 模型的提出者是 Goetz Graefe,其 1994 年發表此文,並於 2017 年得到 Edgar F. Codd(關係模型奠定人)創新獎。
ZNBase 的分佈式執行提出了一些與 Map-Reduce 相似,但與 Map-Reduce 的執行模型又徹底不一樣的概念。
ZNBase 的邏輯計劃由優化後的 Memo 自底而上構建出一個 Plan node 樹狀結構,爲後續構建物理計劃添加一些額外的表信息,列信息等。
分佈式執行的關鍵思想是如何從邏輯執行計劃到物理執行計劃,這裏主要涉及兩方面的處理,一個是計算的分佈式處理,一個是數據的分佈式處理。
一旦生成了物理計劃,系統就須要將其拆分並分佈到各個 node 之間進行運行。每一個 node 負責本地調度數據處理器 data processors 和輸入同步器 synchronizers。node還須要可以彼此通訊以將輸出 output router 鏈接到 input synchronizer。特別是,須要一個 streaming interface 來鏈接這些組件。爲了不額外的同步成本,須要足夠靈活的執行環境以知足上面的全部這些操做,以便不一樣的 node 除了執行計劃初始的調度以外,能夠相對獨立的啓動相應的數據處理工做,而不會受到 gateway 節點的其餘編排影響。
ZNBase 的集羣中的 Gateway node 建立一個 Scheduler 調度器,它接受一組 flow,設置輸入和輸出相關的信息,建立本地 processor 並開始執行。在 node 對輸入和輸出數據進行處理的時候,咱們須要對 flow 進行一些控制,經過這種控制,咱們能夠拒絕 request 中的某些請求。
執行 Flow 示意圖
每一個 Flow 表示整個物理計劃中跨節點執行的一個完整片斷,由 processors 和 streams 組成,能夠完成該片斷的數據拉取、數據計算處理和最終得數據輸出。以下圖所示:
計劃執行示意圖
對於跨節點的執行,Gateway node 首先會序列化對應的 FlowSpec 爲 SetupFlowRequest,並經過 grpc 發送到遠端 node,遠端 node 接收後,會先還原 flow,並建立其包含的 processor 和交互使用的 stream(TCP 通道),完成執行框架的搭建,以後開始由網關節點發起驅動的多節點計算。Flow 之間經過 box 緩存池進行異步調度,實現整個分佈式框架的並行執行。
對於本地執行,就是並行執行,每一個 processor,synchronizer 和 router 均可以做爲 goroutine 運行,它們之間由 channel 互聯。這些 channel 能夠緩衝信道以使生產者和消費者同步。
爲實現分佈式併發執行,ZNBase 在執行時引入了 Router 的概念,對於 JOIN 和AGGREGATOR 等複雜算子根據數據分佈特徵,實現了三種數據再分佈方式,mirror_router、hash_router 和 range_router,經過數據再分佈實現 processor 算子內部拆分爲兩階段執行,第一階段在數據所在節點作部分數據的處理,處理後結果,根據算子類型會進行再分佈後,第二階段聚集處理,從而實現了單個算子多節點協做執行。
小結
本文介紹了基於谷歌 Spanner 論文設計的分佈式 NewSQL 數據庫 ZNBase 的 SQL 引擎架構,並詳細介紹了每一個節點中的鏈接服務、編譯服務、緩存服務,以及系統中的分佈式目錄服務、分佈式執行服務五大服務組件的技術原理與工做流程。下期文章咱們將介紹在原有 SQL 引擎架構的基礎上,ZNBase 團隊針對編譯服務、分佈式執行服務等組件進行的一系列優化改進工做。
關於 ZNBase 的更多詳情能夠查看:
官方代碼倉庫:https://gitee.com/ZNBase/zn-kvs
ZNBase 官網:http://www.znbase.com/
對相關技術或產品有任何問題歡迎提 issue 或在社區中留言討論。同時歡迎廣大對分佈式數據庫感興趣的開發者共同參與 ZNBase 項目的建設。
聯繫郵箱:haojingyi@inspur.com