講解 Task Manager 之前,在這里先介紹一些 Task Manager 會使用到的概念術(shù)語。
荔灣ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
圖數(shù)據(jù)庫 Nebula Graph 中,存在一些長期在后臺運行的任務(wù),我們稱之為 Job。存儲層存在的 DBA 使用的部分指令,比如:數(shù)據(jù)完成導(dǎo)入后,想在全局做一次 compaction,都是 Job 范疇。
作為一個分布式的系統(tǒng),Nebula Graph 中 Job 由不同的 storaged 完成,而我們管一個 storaged 上運行的 Job 子任務(wù)叫做 Task。Job 的控制由 metad 上的 Job Manager 負責(zé),而 Task 的控制由 storaged 上的 Task Manager 負責(zé)。
在本文中,我們著重講述如何對長耗時的 Task 進行管理與調(diào)度進一步提升數(shù)據(jù)庫性能。
上文說到 storaged 上的 Task Manager 控制的 Task 是 meta 控制的 Job 的子任務(wù),那 Task Manager 它自己具體解決什么問題呢?在 Nebula Graph 中 Task Manager 主要解決了以下 2 個問題:
在 Task Manager 體系中, metad(JobManager)的任務(wù)是根據(jù) graphd 中傳過來的一個 Job Request,選出對應(yīng)的 storaged host,并拼組出 Task Request 發(fā)給對應(yīng)的 storaged。不難發(fā)現(xiàn),體系中 meta 接受 Job Request,拼組 Task Request , 發(fā)送 Task Request 及接受 Task 返回結(jié)果,這些邏輯的套路是穩(wěn)定的。而如何拼組 TaskRequest,將 Task Request 發(fā)給哪些 storaged 則會根據(jù)不同的 Job 有所變化。JobManager 用
模板策略
+
簡單工廠
以應(yīng)對未來的擴展。
讓未來的 Job 同樣繼承于 MetaJobExecutor,并實現(xiàn) prepare() 和 execute() 方法即可。
之前提到的,Task Manager 的調(diào)度控制希望做到 2 點:
Task Manager 將系統(tǒng)資源中自己持有的線程稱之為 Worker。Task Manager 有一個現(xiàn)實中的模擬原型——銀行的營業(yè)廳。想象一下, 我們?nèi)ャy行辦業(yè)務(wù)時會有以下幾步:
同時, 你還會碰到這樣那樣的問題:
那么, 整理一下, 這也就是 Task Manager 的基本需求
于是, 有了如下實現(xiàn):
保證不超過閾值還是很簡單的,因為 Worker 就是線程,只要讓所有的 Worker 都出自一個線程池,就可以保證最大的 Worker 數(shù)。麻煩的是將子任務(wù)平均地分配到 Worker 中, 我們來討論下方案:
最簡單的方法是用 Round-robin 的方式來添加任務(wù)。也就是將 Task 分解為 Sub Task 之后, 依次追加到現(xiàn)在的各個 Worker 中。
但是可能會有問題, 比如說, 我有 3 個 Worker, 2 個 Task(藍色為 Task 1,黃色為 Task 2):
Round-robin 圖 1
假如 Task 2 中的 Sub Task 執(zhí)行遠快于 Task1 的, 那么好的并行策略應(yīng)該是這樣:
Round-robin 圖 2
簡單粗暴的 Round-robin 會讓 Task 2 的完成時間依賴于 Task 1(見 Round-robin 圖1)。
針對方法一可能會出現(xiàn)的情況,設(shè)定專門的 Worker 只處理指定的 Task,從而避免多個 Task 相互依賴問題。但是依然不夠好, 比如說:
很難保證每個 Sub Task 執(zhí)行時間基本相同,假設(shè) Sub Task 1 的執(zhí)行明顯慢于其他的 Sub Task,那么好的執(zhí)行策略應(yīng)該是這樣的:
這個方案還是避免不了 1 核有難,10 核圍觀的問題 ????。
在 Nebula Graph 中 Task Manager 會將 Task 的 Handle 交給 N 個 Worker。N 由總 Worker 數(shù)、總 Sub Task 數(shù),以及 DBA 在提交 Job 時指定的并發(fā)參數(shù)共同決定。
每個 Task 內(nèi)部維護一個 Blocking Queue(下圖的 Sub Task Queue),存放 Sub Task。Worker 在執(zhí)行時,根據(jù)自己持有的 Handle 先找到 Task,再從 Task 的 Block Queue 中獲取 Sub Task。
問題 1: 為什么不直接將 Task 放到 Blocking Queue 排隊,而是拆成兩部分,將 Task 保存在 Map 里,讓 Task Handle 排隊?
主要原因是 C++ 多線程基礎(chǔ)設(shè)施不好支持這種邏輯。Task 需要支持 cancel。假設(shè) Task 放在 Blocking Queue 中,就需要 Blocking Queue 支持定位到其中的某一個 Task 的能力。而當(dāng)前 folly 中的 Blocking Queue 都沒有此類接口。
問題 2: 什么樣的 Job 有 VIP 待遇?
當(dāng)前 Task Manager 支持的 compaction / rebuild index 對執(zhí)行時間并不敏感,支持類似 count( ) 查詢操作功能尚在開發(fā)中??紤]到用戶希望在一個相對短的時間內(nèi)完成 count() ,那么假如正好碰上了 storaged 在做多個 compaction,還是希望 count(*) 可以優(yōu)先運行,而非在所有 compaction 之后再開始做。
本文中如有任何錯誤或疏漏歡迎去 GitHub:
https://github.com/vesoft-inc/nebula issue 區(qū)向我們提 issue 或者前往官方論壇:
https://discuss.nebula-graph.com.cn/ 的
建議反饋
分類下提建議 ????;加入 Nebula Graph 交流群,請聯(lián)系 Nebula Graph 官方小助手微信號:
NebulaGraphbot
作者有話說:Hi,我是 我是 lionel.liu,是圖數(shù)據(jù) Nebula Graph 研發(fā)工程師,對數(shù)據(jù)庫查詢引擎有濃厚的興趣,希望本次的經(jīng)驗分享能給大家?guī)韼椭缬胁划?dāng)之處也希望能幫忙糾正,謝謝~