OpenMLDB 在線模組架構解析
本文介紹 OpenMLDB 在線模組的架構,歡迎通過以下渠道了解關於 OpenMLDB 的更多資訊
OpenMLDB 使用文檔:OpenMLDB 文檔 (v0.4)
技術交流群:微信群掃碼
1. 概覽
OpenMLDB 的在線模組主要負責特徵腳本上線以後的實時特徵計算,因此對於低延遲、高並發、高可用等有較高的要求。在線架構的主要模組包括 Apache ZooKeeper, nameserver 以及 tablets(進一步包含了SQL engine 和 storage engine)。如下圖顯示了這些模組之間的相互關係。其中 tablets 是整個 OpenMLDB 存儲和計算的核心模組,也是消耗資源做多的模組;ZooKeeper 和 nameserver 主要用於輔助功能,如元數據的管理和高可用等。本文以下將會詳細介紹各個模組的作用。
2. Apache ZooKeeper
OpenMLDB 依賴 ZooKeeper 做服務發現和元數據存儲和管理功能。ZooKeeper 和 OpenMLDB SDK,tablets, namesever 之間都會存在交互,用於分發和更新元數據。
3. Nameserver
Nameserver 主要用來做 tablet 管理以及故障轉移(failover)。當一個 tablet 節點宕機後,nameserver 就會觸發一系列任務來執行故障轉移,當節點恢復後會重新把數據載入到該節點中。同時,為了保證 nameserver 本身的高可用,nameserver 在部署時會部署多個實例,採用了 primary/secondary 節點的部署模式,同一時刻只會有一個 primary 節點。多個 nameserver 通過 ZooKeeper 實現 primary 節點的搶佔。因此,如果當前的 primary 節點意外離線,則 secondary 節點會藉助 ZooKeeper 選出一個節點重新作為 primary 節點。
4. Tablets
Tablet 是 OpenMLDB 用來執行 SQL 和數據存儲的模組,也是整個 OpenMLDB 功能實現的核心以及資源佔用的瓶頸。Tablet 從功能上來看,進一步包含了 SQL engine 和 storage engine 兩個模組。Tablet 也是 OpenMLDB 部署資源的可調配的最小粒度,一個 tablet 不能被拆分到多個物理節點;但是一個物理節點上可以有多個 tablets。
4.1 SQL Engine
SQL engine 負責執行 SQL 查詢計算。SQL engine 收到 SQL 查詢的請求後的執行過程如下圖所示:
SQL 引擎通過 ZetaSQL 把 SQL 解析成AST語法樹。因為我們加入了 LAST
JOIN
,WINDOW``UNION
等針對特徵工程擴展的特殊 SQL 語法,所以對開源的 ZetaSQL 做了優化。經過如上圖一系列的編譯轉化、優化,以及基於 LLVM 的 codegen 之後,最終生成執行計劃。SQL 引擎基於執行計劃,通過 catalog 獲取存儲層數據做最終的 SQL 執行運算。在分散式版本中,會生成分散式的執行計劃,會把執行任務發到其他 tablet 節點上執行。目前 OpenMLDB 的 SQL 引擎採用 push 的模式,將任務分發到數據所在的節點執行,而不是將數據拉回來。這樣做的好處可以減少數據傳輸。
4.2 Stoage Engine
Storage engine 負責 OpenMLDB 數據的存儲,以及支援相應的高可用相關的功能。
數據分布
OpenMLDB 集群版是一個分散式的資料庫,一張表的數據會進行分片,並且建立多個副本,最終分布在不同的節點中。這裡展開說明兩個重要的概念:副本和分片。
- 副本(replication):為了保證高可用以及提升分散式查詢的效率,數據表將會被存放多個拷貝,這些拷貝就叫做副本。
- 分片(partition):一張表(或者具體為一個副本)在具體存儲時,會進一步被切割為多個分片用於分散式計算。分片數量可以在創建表時指定,但是一旦創建好,分片數就不能動態修改了。分片是存儲引擎主從同步以及擴縮容的最小單位。一個分片可以靈活的在不同的 tablet 之間實現遷移。同時一個表的不同分片可以並行計算,提升分散式計算的性能。OpenMLDB 會自動盡量使得每一個 tablet 上的分片數目盡量平衡,以提升系統的整體性能。一張表的多個分片可能會分布在不同 tablet 上,分片的角色分為主分片(leader)和從分片(follower)。當獲得計算請求時,請求將會被發送到數據所在對應的主分片上進行計算;從分片用於保證高可用性。
如下圖顯示了一個數據表,在兩個副本的情況下,基於四個分片,在三個 tablets 上的存儲布局。實際使用中,如果某一個或者幾個 tablet 的負載過高,可以基於分片,進行數據遷移,來改善系統的負載平衡和整體的吞吐。
數據持久化及主從同步
目前版本的 OpenMLDB 的在線數據全部保存在記憶體中,為了實現高可用會把數據通過 binlog 以及 snapshot 的形式持久化到硬碟中。
如上圖所示,服務端收到 SDK 的寫請求後會同時寫記憶體和 binlog。binlog 是用來做主從同步的,數據寫到 binlog 後會有一個後台執行緒非同步的把數據從 binlog 中讀出來然後同步到從節點中。從節點收到同步請求後同樣是寫記憶體和 binlog。Snapshot 可以看作是記憶體數據的一個鏡像,不過出於性能考慮,snapshot 並不是從記憶體 dump 出來,而是由 binlog 和上一個 snapshot 合併生成。在合併的過程中會刪除掉過期的數據。OpenMLDB會記錄主從同步和合併到 snapshot 中的 offset, 如果一個 binlog 文件中的數據全部被同步到從節點並且也合併到了 snapshot 中,這個 binlog 文件就會被後台執行緒刪除。
注意:在即將發布的 v0.5.0 版本中,OpenMLDB 也會支援基於磁碟的存儲引擎,則其持久化機制會和本文描述不一樣。