今天,我試著簡要綜述幾類不同的圖資料庫的分散式與切圖的設計,希望可以幫助大家瞭解不同專案、產品的設計差異。如果有理解不對的地方,歡迎留言討論。
什麼是分散式系統
一般來說,分散式系統是一組計算機程式的集合,這些程式利用跨多個獨立節點的資源來實現共同的目標;這裡的獨立節點,硬體上大多是指商用伺服器(Commodity Servers)而不是大型主機(Mainframe);這裡的跨節點協同,硬體上大多是基於乙太網裝置或者更高階的 RMDA 裝置。
為什麼我們需要分散式系統?
使用分散式技術的主要目的,本質上是用軟體技術+廉價硬體來換取昂貴硬體裝置(比如主機)的成本;特別是在大多數私有機房環境——而不是公有云端或者超算條件下,此時採購成本是商業決策的重要依據。
除了降低硬體成本外,分散式技術帶來的另一個好處是其“擴充套件性”,透過在原有商用伺服器的數量基礎上,增加幾臺伺服器,再結合分散式軟體的排程和分發能力,使得新加入的這幾臺伺服器也再額外提供更多的服務;
相比於每次擴容都要 1 比 1 採購更多的等數量伺服器,或者購買更高配置的伺服器;分散式技術這一方面使得采購計劃可以按需擴容,降低了一次性的大額資本支出;另一方面也使得業務容量可以更加容易規劃。
分散式系統的基礎問題
在分散式技術中,由於資料的儲存和計算需要跨多個獨立節點來實現,因此不得不涉及到一系列基礎技術。在本文中我們只討論兩個:一是提供資料(和服務)的複製或者副本的問題;二是對於那些龐大資料的儲存和計算該如何分發到各個獨立節點上完成?
一、資料的副本問題
由於是商用伺服器,其硬體上的可靠性和可維護性遠遠低於主機,網線鬆動、硬碟損壞、電源故障在大型機房中幾乎每小時都在發生,是常態;處理遮蔽這些硬體問題是分散式軟體系統要解決的基本問題。一個常用的方式是為資料(和其服務)提供更多的複製或者副本,這些副本存在於多臺商用伺服器上。當一些副本發生故障時,由正常的副本繼續提供服務;並且當訪問壓力增加時,還可以增加更多的副本來增強服務能力。此外,還需要透過一定的技術手段來保證這些副本的“一致性”,也就是每個伺服器上各個副本的資料是一樣的。
當然,在圖資料庫中,副本問題也存在;其處理方式和大多數大資料、RDBMS 會較為類似。
二、是資料的切分問題
單臺伺服器的硬碟、記憶體、CPU 都是有限的,TB、PB 級別的資料透過一定的辦法分發到各個伺服器上,這稱為”切片”。當一些請求要訪問多個切片時,分散式系統要能夠將這些請求拆散分發到各個正確的分片上,並將各分片的返回重新“拼裝”成完整的結果。
圖資料中的切分問題:切圖
在圖資料庫中,這個分發過程被形象的稱為“切圖”:就是把一個大圖切成很多的小圖,把對於這些小圖的儲存或者計算再放置在不同的伺服器上。相比大資料、RDBMS 的大多數方案,值得一些特別的說明。
我們先考慮一個靜態的(不會發生變化的)圖結構,比如“CiteSeer 資料集”,這裡面記錄了 3,312 篇論文,以及這些論文之間的引用關係;這是一個很小規模的資料集,因此工程上,我們可以基本相信對於這個資料集的處理是可以交給單個伺服器。
再對於 twitter2010 這個資料集,其中有 1,271 萬個頂點和 2.3 億條邊,對於今天(2023 年)的主流伺服器來說,相對可以輕鬆處理;但對於 10 年前的伺服器來說,可能就需要選購非常昂貴的高階伺服器才行。
但對於 WDC 資料集(Web Data Commons),其中有 17 億個頂點和 640 億條邊,這樣規模的計算這對於當前單臺主流伺服器來說也相當困難了。
另一方面,由於人類社會資料產生的速度快於摩爾定律,而資料之間的互動與關係又指數級高於資料產生的速度;“切圖”似乎是一個不可避免的問題;但這聽上去似乎和各種主流分散式技術裡面的資料分片和雜湊的方式沒啥區別。畢竟那麼多大資料系統,不都要“切”嗎
等等——圖真的那麼好”切”嗎?
遺憾的是,並不是。圖領域裡面,”切圖”是一個在技術、產品和工程上需要仔細權衡的問題。
切圖面臨的三個問題
第一個問題,切在哪裡?在大資料或者 RDBMS 中,我們根據記錄或者欄位來進行 行切 row-based 或者 列切 column-based,也可以根據 ID 規則進行切分;這些在語義和技術都比較直觀。可是圖的特點是它的強連通性,一個點透過一些邊,關聯上了另外一些點,這些點又透過它們的鄰邊關聯上了更多的點,就像全世界的 Web 網頁,幾乎都透過超連結關聯在一起,那對於圖來說,切在哪裡才是語義上直觀與自然的。(如果用 RDBMS 的術語,相當於有大量的外來鍵情況下,如何切分)。當然,也存在一些天然語義上的圖切片方式,例如在新冠疫情下,各種毒株在中國的傳染鏈條和國外的鏈條已經天然是兩個不同的網路結構。但此時,引入了第二個問題。
第二個問題,如何保證切了之後,各分片的負載是大致均衡的?天然形成的圖符合冪率定律——20% 的少數節點連線了 80% 的其他節點,這些少數節點也稱為“超級節點”或者“稠密點”。這意味著少數超級節點關聯了大多數其他的平平無奇的節點。因此可以預計含有超級節點的分片(伺服器)的負載和熱點會遠遠大於其他不含超級節點的分片。
圖解:網際網路上網站透過超連結形成的關聯網路可視效果,其中的超級網站(節點)清晰可見
第三個問題,當圖網路逐漸演化增長,圖的分佈和連通性也逐漸發生了改變,原有的切分方法逐漸失效,該如何評估和進行重分佈。下圖是人類大腦 860 億個神經元之間的連線可檢視,隨著學習、鍛鍊、睡眠、衰老,神經元連線甚至在周級別就會發生顯著的變化;原先得到的切片方式可能完全跟不上變化。
當然還有其他很多要考慮的問題細節,本文也儘量避免引入太多的技術術語。
遺憾的是,雖然有這些問題(當然其實還有更多),在技術角度並沒有一個通用的最優方案,各個產品針對其重點不得不進行取捨,下面是一些舉例。
不同圖資料庫的切圖方式
1. “分散式”但不”切圖”
這種思路的典型做法是 Neo4j 3.5 雖然採用了分散式的架構,但不進行圖切分。
採用分散式的目的,是為了保證寫入的多副本一致性和讀負載能力。也就是說每個伺服器中都保留了”全量”的圖資料,因此圖資料不能大於單機的記憶體和硬碟容量;而透過增加寫副本,可以保證寫入過程中單機失效問題;透過增加讀副本,可以提供更多的讀請求能力(不能提高寫請求的能力)。
可以看到對於前面的三個問題,這種方案在產品層面直接避免。但是理論上,這樣的方案稱為“分散式”並沒有什麼問題。
多說一句,由於是單機,資料庫意義上的 ACID 在技術上較為簡單。
Neo4j 3.5 的因果叢集架構
https://medium.com/neo4j/querying-neo4j-clusters-7d6fde75b5b4
2. 分散式,由使用者來”切圖”
這個典型的代表是 Neo4j 4.x Fabric。根據業務情況,使用者指定將每個部分的子圖放在一個(組)伺服器上,例如在一個叢集內,E 號產品的圖放在 E 號伺服器上,N 號產品的圖放在 N 號伺服器上。當然,為了服務本身的可用性,這些伺服器還可以採用上文中 Causal Cluster 的方案。
在這個過程中,不論是查詢還是寫入,都需要使用者指定要訪問哪個服務。Fabric 輔助使用者代理路由。這個方案和 RDBMS 的分表非常類似,使用者在使用過程中自己指定要使用那個分割槽或者分表,“切分”這個動作,使用者是有著完全的掌控。
可以看到對於前面的三個問題,這種方案在產品層面完全交給了使用者來決定。當然,這樣的方案也可以稱為“分散式”。
多說一句,雖然可以保證 E 伺服器內部的 ACID。但因為存在一定數量的邊”橫跨”兩個伺服器,技術上不保證這些”橫跨”邊操作的 ACID。
Neo4j Fabric 架構
https://neo4j.com/developer/neo4j-fabric-sharding/
3. 非對等分散式,”切圖”, 粗顆粒度的副本
在這種方案中,既有多副本,也有“切圖”,這兩個過程也都需要少量使用者的介入。
Tigergraph 的切圖方案,可訪問影片檢視:https://www.youtube.com/watch?v=pxtVJSpERgk
在 TigerGraph 的方案中,點和邊(在編碼後),會分散到多個分片上。
上面的三個問題,第 1 和 2 可以透過編碼部分的技巧來部分緩解,並將部分查詢或者計算的決策(單機還是分散式模型)交給使用者決定來實現權衡。
TigerGraph 的單機查詢模式和平行計算模式
多說一句,這樣一組分片必需要完整並一模一樣的複製多份(因此擴容顆粒度是整個圖,而不是某個分片)。相對擴容時的單次支出較大。
4. 全對等分散式,”切圖”,細顆粒度的副本
還有一些方案的架構設計目的中,相對把圖的擴充套件性/彈性排在整個系統設計最高的優先順序。其假設是資料產生的速度快於摩爾定律,而資料之間的互動與關係又指數級高於資料產生的速度。因此,必須要能夠處理這樣爆炸增長的資料,並快速提供服務。
在這種架構中,通常的顯著特點是把儲存層和計算層物理上分開,各自實現細顆粒度的擴容能力;
資料分片由儲存層負責,通常用 hash 或者一致性 hash 的方案進行切分,根據點的 ID 或者主鍵進行雜湊。(回答第一個問題)
NebulaGraph 的架構圖如上,引用自論文:Wu, Min, et al. "Nebula Graph: An open source distributed graph database." arXiv preprint arXiv:2206.07278 (2022).
圖引用自:Li C, Chen H, Zhang S, et al. ByteGraph: A High-Performance Distributed Graph Database in ByteDance[J].
為了處理超級節點和負載均衡(第二個問題),再引入一層資料結構 B+tree,將大的超級節點拆分成更多小的處理單元,並工程上實現執行緒間的負載切換,和獨立擴容計算層。對於第三個問題,透過引入細顆粒度的切片,單獨實現部分切片的擴容
當然,這種方案也可以稱為“分散式”。
以上四種方案,在產品和技術層面做了不同的權衡,各種側重以適合各自的使用者業務場景。但它們都可以稱為“分散式”。
擴充套件閱讀
圖的切分問題:在單機上如何進行切圖,已經得到了大量的研究。這裡推薦工具 METIS (http://glaros.dtc.umn.edu/gkhome/metis/metis/overview)在分散式環境的切圖是一個比(fei)較(chang)困難的問題。這裡推薦一些業界的討論:
關於“偽分散式”(Pseudo-Distrubuted Mode)
一般來說,這是用單伺服器上的執行模擬在多個伺服器的執行;特別適合於學習或者除錯。
關於圖領域的綜述
- Sahu, S., Mhedhbi, A., Salihoglu, S., Lin, J., ¨Ozsu, M.T.: The ubiquity of large graphs and surprising challenges of graph processing: extended survey. VLDB J. 29(2-3), 595–618 (2020)
- Sakr, S., Bonifati, A., Voigt, H., Iosup, A., Ammar, K., Angles, R., Yoneki: The future is big graphs: a community view on graph processing systems. Communications of the ACM 64(9), 62–71 (2021)
Disclaimer
1.以上提到的技術方案,是作者的理解和分享,如有錯誤歡迎指出,並沒有商業競爭目的。
2.為了降低讀者理解難度,做了很大程度的簡化,並不表示原方案是如此簡單。
謝謝你讀完本文 (///▽///)
NebulaGraph Desktop,Windows 和 macOS 使用者安裝圖資料庫的綠色通道,10s 拉起搞定海量資料的圖服務。通道傳送門:http://c.nxw.so/6TWJ0
想看 nebula-br 原始碼的小夥伴可以前往 GitHub 閱讀、使用、(^з^)-☆ star 它 -> GitHub;和其他的 NebulaGraph 使用者一起交流圖資料庫技術和應用技能,留下「你的名片」一起玩耍呢~