圖數據庫綜述與 Nebula 在圖數據庫設計的實踐

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

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

image.png

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

image.png

image.png

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

圖數據庫是什麼

image.png

圖領域的 OLAP & OLTP 場景

image.png

對於圖計算或者圖數據庫本身我們是這麼理解的,它跟傳統數據庫很類似,也分爲 OLAP 和 OLTP 兩個方向。

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

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

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

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

圖數據庫及其他數據庫的關注度增長趨勢

image.png

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

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

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

圖數據存儲計算什麼數據

image.png

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

圖數據的常見多對多關係數據庫場景

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

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

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

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

image.png

圖數據庫的應用場景

剛纔提到的是常見的關係網絡,這裏是我們思考的一些應用場景。

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

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

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

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

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

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

最後一塊是公共安全領域,比如,某些犯罪是團伙作案,那麼追蹤團伙中某個人的行爲軌跡,比如:交通工具、酒店等等就可標識出整個團伙的特徵。某個攝像頭和某個嫌疑人在某個時間構建起來關聯關係,下一個時刻,另外一個攝像頭和另外一個嫌疑人也建立了關聯。這個圖不是靜態的,它是時序的。
這些就是一些已經看到的圖的應用領域。

圖數據庫面臨的挑戰

image.png

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

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

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

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

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

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

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

圖數據庫模型:原生圖數據庫 vs 多模數據庫

image.png

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

對於圖原生的產品,在設計時考慮了圖數據的特性,存儲、計算引擎都是基於圖的特點做了特別設計和優化。

而對於多模的產品,就有很多,比如說 ArangoDB 或者 Orientdb,還有一些雲廠商的服務。它們的底層是一個表或文檔型數據庫,在上層增加圖的服務。對於這類多模數據庫,圖服務層所做的操作,比如:遍歷、寫入,最終將被映射到下面的存儲層,成爲一系列表和文檔的操作。所以它最大的問題是整個系統並不是爲了圖這種多對多的結構特點設計,一旦數據量或者併發量增大之後,問題就比較明顯。我們最近碰到一個比較典型的 case,客戶使用多模 DB,在數據量很小時還比較方便,但當數據量大到一定程度,做二跳三跳查詢時 touch 的數據非常多,而多模 DB 底層是關係型數據庫,所有關係最終要映射到關係型數據庫的 join  操作,做三四層的 join ,性能會非常的差。

圖數據庫——Nebula Graph:一個開源的分佈式圖數據庫

image.png

上面是我們對行業的一些思考。這裏是我們在做的圖數據庫,它是一個開源的分佈式的項目——Nebula Graph

存儲設計

image.png

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

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

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

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

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

至於數據強一致這個挑戰,有主要分兩個方面,一個是關於數據的強一致,就是多數派協議——Nebula 現在使用的 Raft 協議,通過多副本的方式來實現強一致。另外個是分佈式的事物務 Transaction,它來保證要向多臺機器寫入一批相互依賴數據的正確性,這個和 NewSQL 裏面的概念是非常類似的。

計算設計

image.png

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

前面提到的一個技術挑戰是低延時、高併發,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。

架構設計

image.png

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 的查詢引擎設計

image.png

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

查詢語言——nGQL

image.png

先來介紹下 Nebula 的查詢語言 nGQL。nGQL 的子查詢有三種組合方式:管道、分號和變量。
nGQL 支持實時的增刪改、圖遍歷、屬性遍歷,也支持對屬性先做 index 再遍歷。此外,你還可以對圖上的路徑寫個正則表達式,查找所有滿足這個條件的圖路徑。

查詢引擎架構

image.png

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

執行計劃案例

image.png

這裏有個小例子展示了執行計劃,下方就是一條語句。首先 use myspace,這裏的 space 和數據庫裏的 database 是一個概念,每個 space 是一個物理隔離的空間,可用來區分敏感數據和非敏感數據,或者說做多租戶的支持。分號後面是下一語句—— INSERT VERTEX 插入節點, GO 是網絡拓展, | 爲 Nebula 的管道用法,這條語句的意思是將第一條 Go 的結果傳給第二條 Go,然後再傳給第三條,即往外走三步遍歷,最後把整個結果做求和運算。這是一種常見的寫法,Nebula 還支持其他寫法。

這樣語句的執行計劃就會變成上圖右邊的語法執行樹。這裏每個節點,都叫做Executor(語法執行者),語句中的分號對應執行 SequentialExecutor ,Go 對應執行 GoExecutor ,"|"(管道)對應執行 PipeExecutor 。

執行優化

image.png

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

圖數據庫 Nebula 的存儲引擎設計

image.png

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

存儲架構

image.png

這張圖其實是前面整體架構圖的下面部分。縱向可理解爲一臺機器,每臺機器最上面是 Storage service,綠色的桶是數據存儲,數據被切分成很多個分片 partition,3 臺機器上同 id 的 partition 組成一個 group,每個 group 內用 Raft 協議實現多副本一致性。Partition 的數據最後落在 Store Engine 上,Nebula 默認 Store Engine 是 RocksDB。這裏再提一下,partition 是個邏輯概念,partition 數量多少不會額外增加內存,所以一般把 partition 數量設置成遠大於機器的數量。

Schema

image.png

這一頁是 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 間可存在多筆轉賬,那每筆轉賬就是一條邊。
上面例子中,點和邊都帶有屬性,即多組<k,v>。Nebula是一個強 schema 系統,屬性的每個字段名和對應的類型需要在構圖時先定義,和數據庫中的 alter table 類似 Nebula 也支持你在後續操作中進行 Schema 更改。Schema 中還有常見的 TTL(Time To Live),指定特定數據的生命週期,數據時效到後這條數據會被自動清理。

數據分片和 Key 的設計

image.png

剛纔有提到過分片(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 上的,這樣就不涉及跨網絡開銷,最多一次硬盤讀就可以取到對應數據。

多副本和高可用

image.png

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

image.png

容錯機制

Nebula 對於容錯或者說高可用的保證,主要依賴於 Raft 協議。這樣單機 Crash 對服務是沒有影響的,因爲用了 3 副本。那要是 Meta Server 掛了,也不會像 HDFS 的 NameNode 掛了影響那麼大,這時只是不能新建 schema,但是數據讀寫沒有影響,這樣做 meta 的遷移或者擴容也比較方便。

image.png

最後是 Nebula 的 GitHub 地址,歡迎大家試用,有什麼問題可以向我們提 issue。GitHub 地址:https://github.com/vesoft-inc/nebula

Nebula Graph:一個開源的分佈式圖數據庫。

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

知乎:https://www.zhihu.com/org/neb...

微博:https://weibo.com/nebulagraph

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章