天天看點

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

Nebula Graph :一個開源的分布式圖資料庫。作為唯一能夠存儲萬億個帶屬性的節點和邊的線上圖資料庫,Nebula Graph 不僅能夠在高并發場景下滿足毫秒級的低延遲時間查詢要求,還能夠實作服務高可用且保障資料安全性。

第三期 nMeetup( nMeetup 全稱:Nebula Graph Meetup,為由開源的分布式圖資料庫 Nebula Graph 發起的面向圖資料庫愛好者的線下沙龍) 活動于 2019 年 8 月 3 日在上海陸家嘴的彙豐銀行大樓舉辦,我司 CEO -- Sherman 在活動中發表《 Nebula Graph Internals 》主題演講 。本篇文章是根據此次演講所整理出的技術幹貨,全文閱讀需要 30 分鐘,我們一起打開圖資料庫的知識大門吧~

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

大家好,非常感謝大家今天能夠來我們這個線下沙龍,天氣很熱,剛又下了暴雨,說明大家對圖資料庫的熱情要比夏天溫度要高。今天我們準備了幾個 topic,一個就是介紹一下我們産品——Nebula 的一些設計思路,今天不講介紹性東西,主要講 Nebula 内部的思考——為什麼會去做 Nebula,怎麼樣去做,以及為什麼會采取這樣的設計思路。

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐
圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這個就是 Nebula。先從 overview 介紹圖資料庫到底是個什麼東西,然後講我們對圖資料庫的一些思考。最後具體介紹兩個子產品, Nebula 的 Query Service 和 Storage Service。後面兩部分會稍微偏技術一些,在這個過程當中如果大家遇到什麼問題,歡迎随時提出。

圖資料庫是什麼

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

圖領域的 OLAP & OLTP 場景

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

對于圖計算或者圖資料庫本身我們是這麼了解的,它跟傳統資料庫很類似,也分為 OLAP 和 OLTP 兩個方向。

上圖中下面這根軸表示資料對查詢時效性的要求,OLAP 更偏向于做離線分析,OLTP 更偏向于線上處理。我們認為圖領域也可以這麼劃分。

首先在 OLAP 這個領域,我們稱為圖計算架構,這些圖計算架構的主要目的,是做分析。基于圖的結構的分析——這裡圖代指一個關系網絡。整體上這個分析比較類似于傳統資料庫的 OLAP。但一個主要特點就是基于圖結構的疊代算法,這個在傳統資料庫上是沒有的。最典型的算法是谷歌 PageRank,通過一些不斷的疊代計算,來算網頁的相關度,還有非常常見的 LPA 算法,使用的也非常多。

如果我們繼續沿着這個線向右邊延伸,可以看到一個叫做 Graph Stream 的領域,這個領域相當于圖的基礎計算跟流式計算相結合的産物。大家知道關系網絡并不是單單一個靜态結構,而是會在業務中不斷地發生變化:可能是圖的結構,或者圖上的屬性發生變化,當圖結構和屬性發生變化時,我們希望去做一些計算,這裡的計算可能是一種觸發的計算或判斷——例如在變化過程當中是不是動态地在圖上形成一個閉環,或者動态地判斷圖上是否形成一個隔離子圖等等。Trigger(觸發)的話,一般是通過事件來驅動這類計算。對時效性的響應當然是越高越好,但往往響應時間一般是在秒級左右。

那麼再往軸上右邊這個方向看,是線上的線上響應的系統。大家知道這類系統的特點是對延時要求非常高。可以想象如果線上上做交易的時候,在這個交易瞬間,需要到圖上去拿一些資訊,當然不希望要花費秒級。一般響應時間都是在十幾、二十毫秒這樣一個範圍。可以看到最右邊的場景和要求跟左邊的是完全不一樣的,是一種典型的 OLTP 場景。在這種場景裡面,通常是對子圖的計算或者周遊——這個和左邊對全圖做計算是完全不一樣的:比如說從幾個點出發,得到周邊3、4度的鄰居構成一個子圖,再基于這個子圖進行計算,根據計算的結果再繼續做一些圖周遊。是以我們把這種場景稱為圖資料庫。我們現在主要研發内容主要面向OLTP這類場景。是以說今天的一些想法和講的内容,都是跟這塊相關。

圖資料庫及其他資料庫的關注度增長趨勢

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這張圖是從 DB-Engines.com 上截下來的,反應了從 2013 年到 2019 年 7 月,所有類型資料庫的趨勢。這個趨勢是怎麼計算出來的?DB-Engines 通過到各大網站上去爬取内容,檢視所有使用者,包括開發人員和業務人員的情況下統計某類資料庫被提及的次數将其轉化為分數,分數越高,表示這種類型的資料庫的關注度越高。是以說這是一個關注度的趨勢。

最底下這條紅線是關系型資料庫,在關系型資料庫之上有各類資料庫,比如 Key-Value型、文檔型、RDF 等。最上面的綠線就是圖資料庫。

可以看到在過去六年多的時間裡,圖資料庫的整個趨勢,或者說它的影響力大概增長了十倍。

圖資料存儲計算什麼資料

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

今天我們談資料庫肯定離不開資料,因為資料庫隻是一個載體,一個存儲和計算的載體,它裡面的資料到底是什麼呢?就是我們平時說的圖。這裡列出了幾個目前為止比較常見的多對多的關系資料。

圖資料的常見多對多關系資料庫場景

第一個 Social Network(社交網路),比如說微信或者 Facebook 好友關系等等。這個網絡有幾十億個使用者,幾千億到幾萬億的連接配接關系。第二個 Business Relation,商業的關系,常見的有兩種網絡:

  • 金融與資金關系網絡:一種比如說在支付網絡裡面,賬戶和賬戶之間的支付關系或者轉賬關系,這個是比較典型的金融與資金關系網絡;
  • 公司關系:在 business 裡面,比如說公司控股關系,法人關系等等,它也是一個非常龐大的網絡。基于工商總局資料,有許多公司耕耘在這一領域。這個網絡的節點規模也有億到十億的級别,大概幾百億條邊,如果算上交易轉賬資料那就非常龐大了。

第三個是知識圖譜,也是最近比較熱的一個領域。在各個垂直領域會有不同的知識點,且知識點之間有相關性。部分垂直領域知識的網絡至少有幾百億條關系,比如銀行、公安還有醫學領域。

最後就是這幾年熱門的 IoT(Internet of Things)領域,随着近年智能裝置的增長,預計以後 IoT 裝置數量會遠超過人口數量,現在我們每個人身邊佩帶的智能裝置已不止一個,比如說智能手機、智能手表,它們之間組成一個龐大的關系網絡,雖然具體應用有待後續開發,但這個領域在未來會有很大的應用空間。

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

圖資料庫的應用場景

剛才提到的是常見的關系網絡,這裡是我們思考的一些應用場景。

第一個應用場景是基于社交關系網絡的社交推薦,比如:拼多多的商品推薦,抖音的視訊推薦,頭條的内容推薦,都可以基于已有的好友關系來推薦。

第二個就是風控領域,風控其實是銀行保險業的核心話題。傳統的風控是基于規則——基于規則的風控手段,相對已經比較成熟了,一般是拿直接的交易對手來做規則判斷。但現在風控有個新趨勢,就是通過關聯關系做拓展,比如交易對手等相關的周邊賬号,通過這些關系來判斷這筆交易或者轉賬的風險。從規則向基于關聯關系的風控演進,這個趨勢比較明顯。

關于知識圖譜這一塊,和 Google 比較有關,谷歌在 2003,2004 年時候,其實已經在慢慢把它的 search engine,從反向索引轉向轉到了知識圖譜。如果隻有倒排表,比如說要查“特朗普”今年幾歲,這個是很難做到的,因為已有的資訊是他的生日是哪年。

這幾年機器學習和 AI 領域發展非常快,大家知道就機器學習或者模型訓練範疇來說,平時用大量資料去訓練模型,其實歸根結底是對大量資料彙總或者說統計性的結果。最近一兩年,大家發現光有統計性結果不夠,資料和資料之間的關系也應展現在模型裡,是以開始将基于圖的資料關系加入到模型訓練,這個就是學術界非常流行的 Graph Embedding,把圖的結構引入到模型訓練裡面。

在健康和醫療領域,患者的過往病史、服藥史、醫生的處方還存在紙質文檔的情況,一些醫療類公司通過語音和圖像将文檔數字化,再用 NLP 把關鍵資訊提取出來。根據關鍵資訊,比如:血壓、用藥等等構造一棵大的決策樹或者醫療知識圖譜。這塊也是比較新的應用。

區塊鍊的應用其實比較容易了解,區塊鍊本身雖然說是鍊,但有很多分支結構,當分支交織後也就構成一個網絡。舉個簡單例子,A 某想通過比特币洗錢,常用方法是通過多個賬号,幾次轉賬後,資金通過數字貨币形成一個閉環,而這個方法是可以通過圖進行洗錢防範。

最後一塊是公共安全領域,比如,某些犯罪是團夥作案,那麼追蹤團夥中某個人的行為軌迹,比如:交通工具、酒店等等就可辨別出整個團夥的特征。某個攝像頭和某個嫌疑人在某個時間建構起來關聯關系,下一個時刻,另外一個攝像頭和另外一個嫌疑人也建立了關聯。這個圖不是靜态的,它是時序的。

這些就是一些已經看到的圖的應用領域。

圖資料庫面臨的挑戰

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

回到圖資料庫,做圖資料庫到底有哪些挑戰。和所有的 OLTP 系統一樣:

第一個挑戰就是低延時。我們不希望一次查詢,要幾秒鐘甚至幾分鐘才能産生結果。比如說風控場景,線上轉賬的時候,我要判斷這筆交易是否有風險,可能整個時間隻有一百毫秒,留給風控判斷的時間隻有幾十毫秒。不可能轉賬完才發現對方賬戶已經被标黑了,或者這筆交易其實是在套現。

第二個挑戰是高吞吐,現在熱門的 APP,比如抖音或者頭條,日常通路的并發量是非常高的,峰值可能幾十萬 QPS,DB 要能抗的住。

第三個挑戰是資料量激增,資料量的增加速度快于硬體特别是硬碟的增長速度,這個給 DB 帶來了很大的挑戰。大家可能用過一些單機版的圖資料庫,剛開始用覺得不錯,能滿足需求。但一兩年後,發現資料量增加太快,單機版已經完全滿足不了需求,這時總不能把業務流控吧。

我們遇到過一個圖 case,有超過一千億個節點,一萬億條邊,點和邊上都還有屬性,整個圖的資料量超過上百T。可以預計下,未來幾年資料量的增長速度會遠遠快于摩爾定理的速度,是以單機版資料庫肯定搞不定業務需求,這對圖資料庫開發是一個很大的挑戰。

第四個挑戰是分析的複雜性,當然這裡分析指的是 OLTP 層面的。因為圖資料庫還比較新,大家剛開始使用的時候會比較簡單,例如隻做一些 K度拓展。但是随着使用者的了解越來越深,就會提出更多越來越複雜的需求。例如在圖周遊過程中過濾、統計、排序、循環等等,再根據這些計算結果繼續圖周遊。是以說業務需求越來越複雜。這就要求圖資料庫提供的功能越來越多。

最後一個挑戰是關于資料一緻性——當然還有很多其他挑戰,這裡沒有全部羅列。前幾年大家對于圖資料庫的使用方法更像使用二級索引,把較大的資料放在另外的存儲元件,比如 HBase 将關聯關系放在圖資料庫裡,将圖資料庫隻作為圖結構索引來加速。但像剛才說的,業務越來越複雜,對響應時間要求越來越高,原先的架構除了不友善,性能上也有很大挑戰。比如,需要對屬性做過濾時,要從 HBase 讀取出太多資料,各種序列化、過濾操作都很慢。這樣就産生了新需求——将這些資料直接存儲在圖資料庫裡,自然 ACID 的需求也都有了。

圖資料庫模型:原生圖資料庫 vs 多模資料庫

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

說完技術挑戰,還有個概念我想特别澄清下。大家如果網上搜圖資料庫,可能有 20 個自稱圖資料庫的産品。我認為這些産品可以分成兩類,一種就是原生的,還有一類是多模的。

對于圖原生的産品,在設計時考慮了圖資料的特性,存儲、計算引擎都是基于圖的特點做了特别設計和優化。

而對于多模的産品,就有很多,比如說 ArangoDB 或者 Orientdb,還有一些雲廠商的服務。它們的底層是一個表或文檔型資料庫,在上層增加圖的服務。對于這類多模資料庫,圖服務層所做的操作,比如:周遊、寫入,最終将被映射到下面的存儲層,成為一系清單和文檔的操作。是以它最大的問題是整個系統并不是為了圖這種多對多的結構特點設計,一旦資料量或者并發量增大之後,問題就比較明顯。我們最近碰到一個比較典型的 case,客戶使用多模 DB,在資料量很小時還比較友善,但當資料量大到一定程度,做二跳三跳查詢時 touch 的資料非常多,而多模 DB 底層是關系型資料庫,所有關系最終要映射到關系型資料庫的

join

  操作,做三四層的

join

 ,性能會非常的差。

圖資料庫——Nebula Graph:一個開源的分布式圖資料庫

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

上面是我們對行業的一些思考。這裡是我們在做的圖資料庫,它是一個開源的分布式的項目——

存儲設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這裡我想說下我們在設計 Nebula 時候的一些思考,為什麼會這樣設計?

剛剛說到過技術挑戰中資料量迅速膨脹,業務邏輯越發複雜,像這樣的開發挑戰,Nebula 是如何解決的。

Nebula 在設計存儲時,采用 share-nothing 的分布式架構,本質上存儲節點間沒有資料共享,也就是整個分布式結構無中心節點。這樣的好處在于,第一,容易做水準拓展;第二,即使部分機器 Crash,通過資料強一緻性—— Raft 協定能保證整個系統的可用性,不會丢失資料。

因為業務會越發複雜,是以 Nebula 支援多種存儲引擎。有的業務資料量不大但對查詢的實時性要求高,Nebula 支援純記憶體式的存儲引擎;資料量大且查詢并發量也大的情況下,Nebula 支援使用記憶體加 SSD 模式。當然 Nebula 也支援第三方存儲引擎,比如,HBase,考慮到這樣使用存在的主要問題是性能不佳,我們建議用在一些對性能要求不是很高的場景。

第三個設計就是把存儲和計算這兩層分開了——也就是“存儲計算分離”。這樣的設計有幾個明顯的好處。所有資料庫在計算層通常都是無狀态的,CPU intensive,當 CPU 的計算力不夠的時候,容易彈性擴容、縮容,而對于存儲層而言,涉及到資料的搬遷情況要複雜些。是以當存儲計算分離後,計算層和存儲層可以根據各自的情況彈性調整。

至于資料強一緻這個挑戰,有主要分兩個方面,一個是關于資料的強一緻,就是多數派協定——Nebula 現在使用的 Raft 協定,通過多副本的方式來實作強一緻。另外個是分布式的事物務 Transaction,它來保證要向多台機器寫入一批互相依賴資料的正确性,這個和 NewSQL 裡面的概念是非常類似的。

計算設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

剛剛是我們對存儲引擎的一些思考,這裡是我們對計算引擎的思考。

前面提到的一個技術挑戰是低延時、高并發,Nebula 整個的核心代碼都是 C++ 寫的,這樣保證了執行效率。其次,做了很多并行和異步執行的優化。第三個是計算下推。在分布式系統裡面,硬體上網絡對整體性能的影響最大,是以資料搬遷是一個很低效的動作。有些開源圖資料庫産品,比如 JanusGraph,它的存儲層在 HBase,上面有個單獨的計算層,當計算層需要資料的時候,會到 HBase 裡面拉回大量的資料,再做過濾和計算。舉個例子,1 萬條資料裡面最終過濾出 100 條,那相當于 99% 的網絡傳輸都浪費了。是以 Nebula 的設計方案是移動計算,而不是資料,計算下推到存儲層,像前面這個例子,直接在存儲層做完過濾再回傳計算層,這樣可以有 100 倍的加速。

第二,如果大家接觸過圖資料庫領域的一些産品,會發現圖資料庫這領域,相比關系型資料庫有個很大的問題——沒有通用的标準。關系型領域的标準在差不多 30 年前已制定,但圖資料庫這個領域各家産品的語言相差很大。那麼針對這個問題 Nebula 是怎麼解決?第一盡量貼近 SQL,哪怕你沒有學過 Nebula 語言,你也能猜出語句的作用。是以 Nebula 的查詢語言和 SQL 很像,為描述性語言,而不是指令式語言。第二個是過去幾年我們做圖資料庫領域的經驗積累,就是 No-embedding(無嵌套)。SQL 是允許 embedding 的,但嵌套有個問題——當查詢語句過長時,語句難讀,因為 SQL 語句需從内向外讀,語序正好跟人的了解相反,因為人比較習慣從前往後來了解。是以Nebula 把嵌套語句寫成從前往後的方式,作為替代,提供 Shell 管道這樣的方式,即前面一條指令的輸出作為後一條指令的輸入。這樣寫出來的語句比較容易了解,寫了一個上百行的 query 你就會發現從前往後讀比從中間開始讀要易于了解。

第三,和傳統資料庫相比,圖的計算不光是 CRUD,更重要是基于圖結構的算法,加上新的圖算法不停地湧現,Nebula 怎麼 keep up?

  • 将部分主要算法 build in 到查詢引擎裡;
  • 通過支援 UDF(user-defined function,使用者定義函數),使用者可把業務相關邏輯寫成程式或者函數,避免寫重複 query;
  • 查詢語言的程式設計能力:Nebula 的查詢語言 nGQL 是 Programmable。

架構設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

Overview 這一章節的最後内容是 Nebula 的架構。上圖虛線把存儲和計算一分為二,上面是整個計算層,每一台機器或者虛拟機是一個節點,它是無狀态的,互相之間沒有任何通訊,是以計算層要做擴縮容非常容易。

下面是存儲層,有資料存儲是以是有狀态的。存儲層還可以細分,第一層是 Storage Service,從計算層傳來的請求帶有圖語義資訊,比如:鄰居點、取 property,Storage Service 的作用是把圖語義變成了 key-value 語義交給下層的 KV-store,在 Storage Service 和 KV-store 之間是一層分布式 Raft 協定。

圖的右邊是 Meta Service,這個子產品有點類似 HDFS 的 NameNode,主要提供兩個功能,一個是各種元資訊,比如 schema,還有一個是指揮存儲擴容。大家都知道存儲擴容是個非常複雜的過程,在不影響線上業務地情況下一步步增加機器,資料也要一點點搬遷,這個時候就需要有個中心指揮。另外 Meta Service 本身也是通過 Raft 來保證高可用的。

圖資料庫 Nebula 的查詢引擎設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

上面就是 Nebula 的總體介紹,下面這個部分介紹查詢引擎的設計細節。

查詢語言——nGQL

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

先來介紹下 Nebula 的查詢語言 nGQL。nGQL 的子查詢有三種組合方式:管道、分号和變量。

nGQL 支援實時的增删改、圖周遊、屬性周遊,也支援對屬性先做 index 再周遊。此外,你還可以對圖上的路徑寫個正規表達式,查找所有滿足這個條件的圖路徑。

查詢引擎架構

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

再來介紹下查詢引擎的架構,從查詢引擎的架構圖上來看,和資料庫類似:從用戶端發起一個請求(statement),然後 Parser 做詞法分析,之後把分析結果傳給執行計劃(Execution Planner),執行計劃會基于這個語句的特點,交給優化器(Optimizer)進行優化,最後将結果交給執行引擎(Execution Engine)去執行。執行引擎會通過 MetaService 擷取點和邊的 schema,通過存儲引擎層擷取點和邊的資料。

執行計劃案例

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這裡有個小例子展示了執行計劃,下方就是一條語句。首先 use myspace,這裡的 space 和資料庫裡的 database 是一個概念,每個 space 是一個實體隔離的空間,可用來區分敏感資料和非敏感資料,或者說做多租戶的支援。分号後面是下一語句——

INSERT VERTEX

 插入節點,

GO

 是網絡拓展,

|

 為 Nebula 的管道用法,這條語句的意思是将第一條 Go 的結果傳給第二條 Go,然後再傳給第三條,即往外走三步周遊,最後把整個結果做求和運算。這是一種常見的寫法,Nebula 還支援其他寫法。

這樣語句的執行計劃就會變成上圖右邊的文法執行樹。這裡每個節點,都叫做Executor(文法執行者),語句中的分号對應執行

SequentialExecutor

 ,Go 對應執行

GoExecutor

 ,"|"(管道)對應執行

PipeExecutor

 。

執行優化

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這一頁介紹執行優化。在順序執行過程中優化器會判斷目前語句是否存在互相依賴關系,在沒有互相依賴時,執行引擎可并行執行進而加速整個執行過程,降低執行延時。流水線優化,跟處理器 CPU 的流水線優化類似。上面“GO … | GO … | GO … ”例子中,表面上第一個 GO 執行完畢後再把結果發給第二個 GO 執行,但實際執行時,第一個 GO 部分結果出來之後,就可以先傳給下一個GO,不需要等全部結果拿到之後再傳給下一步,這對提升時延效果明顯。當然不是所有情況都能這樣優化,裡面有很多工作要做。前面已提過計算下沉的優化,即過濾的操作盡量放在存儲層,節省通過網絡傳輸的資料量。JIT 優化在資料庫裡已經比較流行,把一條 query 變成代碼直接去執行,這樣執行效率會更高。

圖資料庫 Nebula 的存儲引擎設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

剛才介紹了查詢引擎,下面介紹存儲引擎。

存儲架構

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這張圖其實是前面整體架構圖的下面部分。縱向可了解為一台機器,每台機器最上面是 Storage service,綠色的桶是資料存儲,資料被切分成很多個分片 partition,3 台機器上同 id 的 partition 組成一個 group,每個 group 内用 Raft 協定實作多副本一緻性。Partition 的資料最後落在 Store Engine 上,Nebula 預設 Store Engine 是 RocksDB。這裡再提一下,partition 是個邏輯概念,partition 數量多少不會額外增加記憶體,是以一般把 partition 數量設定成遠大于機器的數量。

Schema

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

這一頁是 schema,講的是怎麼把圖資料變成 KV 存儲。這裡面的第一個概念是标簽(Tag),“标簽”表示的是點(Vertex)的類型,一個點可以有多種“标簽”或者說“類型”。另一個概念是邊類型(Edge Type),一條邊需要用起點 ID,終點 ID,邊類型和 Ranking 來唯一辨別。前面幾個字段比較好了解,Ranking 這個字段是留給客戶表示額外資訊,比如:轉賬時間。這裡補充下說明下 Nebula 頂點 Vertex、标簽 Tag、邊 Edge、邊類型 Edge Type的關系。

Vertex 是一個頂點,用一個 64 位的 id 來辨別,一個 Vertex 可以被打上多個 Tag(标簽),每個 Tag 定義了一組屬性,舉個例子,我們可以有 Person 和 Developer 這兩個 Tag,Person 這個 Tag 裡定義了姓名、電話、住址等等資訊,Developer 這個 Tag 裡可能定義了熟悉的程式設計語言、工作年限、GitHub 賬号等等資訊。一個 Vertex 可以被打上 Person 這個 Tag,這就表示這個 Vertex 代表了一個 Person,同時也包含了 Person 裡的屬性。另一個 Vertex 可能被同時打上了 Person 和 Developer 這兩個 Tag,那就表示這個 Vertex 不僅是一個 Person,還是一個 Developer。

Vertex 和 Vertex 之間可以用 Edge 相連,每一條 Edge 都會有類型,比如:好友關系。每個 Edge Type 可定義一組屬性。Edge 一般用來表示一種關系,或者一個動作。比如,Peraon A 給 Person B 轉了一筆錢,那 A 和 B 之間就會有一條 Transfer 類型的邊,Transfer 這個邊類型(Edge Type)可以定義一組屬性,比如轉賬金額,轉賬時間等等。任何兩個 Vertex 之間可以有多種類型的邊,也可以有多條同種類型的邊,比如:轉賬,兩個 Person 間可存在多筆轉賬,那每筆轉賬就是一條邊。

上面例子中,點和邊都帶有屬性,即多組。Nebula是一個強 schema 系統,屬性的每個字段名和對應的類型需要在構圖時先定義,和資料庫中的 alter table 類似 Nebula 也支援你在後續操作中進行 Schema 更改。Schema 中還有常見的 TTL(Time To Live),指定特定資料的生命周期,資料時效到後這條資料會被自動清理。

資料分片和 Key 的設計

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

剛才有提到過分片(Partition)和鍵(Key)的設計,這裡再詳細解釋一下。

資料分片 Partition 或者有些系統叫 Shard,它的 ID 是怎麼得到?非常簡單,根據點的 ID 做 Hash,然後取模 partition 數量,就得到了 PartitionID。

Vertex 的 Key 是由 PartID + VID + TagID 三元組構成的,Value 裡面存放的是屬性(Property),這些屬性是一系列 KV 對的序列化。

Edge 的 Key 是由 PartID + SrcID + EdgeType + Ranking + DstID 五元組構成,但邊和點不同:一個點在 Nebula 裡隻存儲一個 KV,但在 Nebula 中一條邊會存兩個 KV,一個 Out-edge Key和一個 In-edge Key,Out-edge 為圖論中的出邊,In-edge 為圖論中的入邊,雖然兩個 Key 都表示同一條邏輯邊,但存儲兩個 KV 的好處在于周遊時,友善做出度和入度的周遊。

舉個例子:要查詢過去 24 小時給我轉過錢的人,即查找所有指向我的賬号,周遊的時候從“我”這個節點開始,沿着邊反向走可以看到 Key 的設計是入邊 In-edge 的 DstID 資訊在前面。是以做 Key 查詢時,入邊和終點,也就是“我”和“指向我的邊”是存儲在一個分片 Partition 上的,這樣就不涉及跨網絡開銷,最多一次硬碟讀就可以取到對應資料。

多副本和高可用

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

最後再談下資料多副本和 Failover 的問題。前面已經提到多副本間是基于 Raft 協定的資料強一緻。Nebula 在 Raft 做了些改進,比如,每組 partition 的 leader 都是打散的,這樣才可以在多台機器并發操作。此外還增加了 Raft learner 的角色,這個角色不會參與 Raft 協定的投票,隻負責從 leader 讀資料。這個主要應用于一個資料中心向另外一個資料中心做異步複制場景,也可用于複制到另外第三方存儲引擎,比如:HBase。

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

容錯機制

Nebula 對于容錯或者說高可用的保證,主要依賴于 Raft 協定。這樣單機 Crash 對服務是沒有影響的,因為用了 3 副本。那要是 Meta Server 挂了,也不會像 HDFS 的 NameNode 挂了影響那麼大,這時隻是不能建立 schema,但是資料讀寫沒有影響,這樣做 meta 的遷移或者擴容也比較友善。

圖資料庫綜述與 Nebula 在圖資料庫設計的實踐

最後是 Nebula 的 GitHub 位址,歡迎大家試用,有什麼問題可以向我們提 issue。GitHub 位址:

https://github.com/vesoft-inc/nebula

Nebula Graph:一個開源的分布式圖資料庫。

GitHub:

官方部落格: https://nebula-graph.io/cn/posts/ 微網誌: https://weibo.com/nebulagraph