Nebula Graph:一個開源的分佈式圖數據庫。做爲惟一可以存儲萬億個帶屬性的節點和邊的在線圖數據庫,Nebula Graph 不只可以在高併發場景下知足毫秒級的低時延查詢要求,還可以實現服務高可用且保障數據安全性。git
HBaseCon Asia2019 活動於 2019 年 7 月 20 日於北京金隅喜來登酒店舉辦,應主辦方邀請,Nebula Graph 技術總監-陳恆在活動中發表演講 「Nebula: A Graph DB based on HBase」 。本篇文章是根據這次演講所整理出的技術乾貨,全文閱讀須要 30 分鐘。github
你們下午好,我是陳恆,來自 VESoft,是開源圖數據庫 Nebula Graph 的開發者。同時,我也是 HBase 的 Commiter<del>(剛纔在後面和各位大佬談笑風生)</del>,今天和你們分享的,是咱們最近剛開源的分佈式圖數據庫 Nebula Graph。算法
首先,介紹一下咱們公司:歐若數網科技有限公司(英文名:VESoft),是 2018 年 10 月份成立的。咱們的核心產品是分佈式圖數據庫 Nebula Graph,這個項目從開始到如今,大概作了半年多時間。目前已經 release alpha 版本,還有能夠試用的 docker,正式的 release 預計會在 10 月份。docker
NebulaGraph 是徹底開源的,能夠在 GitHub 上訪問 https://www.github.com/vesoft-inc/Nebula數據庫
下面咱們看一張圖,是 DB-Engine 的統計,反映了從 2013 年到今年全部的 NoSQL 類數據庫的發展趨勢。橫軸表明的是時間,縱軸能夠認爲是受衆程度,或者社區裏的討論熱烈程度。你們能夠看到綠色的線就是圖數據庫。這些年一共翻了十倍,增加仍是很是迅猛的。後端
在座的同事是 HBase 專家,部分可能對於圖數據庫有些不太瞭解,我這裏簡單介紹一下圖數據庫。它的主要應用場景實際上是針對於各類各樣的點和邊組成的數據集合。緩存
舉幾個例子來說,典型圖數據庫的應用場景有如下幾個。安全
社交場景是一個咱們常見的社交場景,就是好友之間的關係。這個天然而然構成了一張圖。好比說:在社交場景裏面,作推薦算法。爲某我的推薦他的好友。如今典型的方法都是去找好友的好友,而後看好友的好友有沒有可能成爲新的好友。這裏面可能會有各類親密度關係,以及各類各樣的排序。傳統來說,咱們可能會利用 MySQL 或者是 HBase 存各類各樣的好友關係,而後經過多個串行的 Key Value 訪問來查。可是真正在線上場景裏面的話,是很難知足性能要求的。因此,另一種作法是利用離線計算。把可能的好友關聯和推薦都離線計算好。而後,查的時候直接去讀已經準備好的數據,但這個問題就在於時效性比較差。對於有一些對於時效性要求比較高的場景,這樣是不能夠接受的。後面我有一些 case 能夠來談這個事情。網絡
商業關係網絡:數據庫的使用場景除了社交網絡外,還有商業關係網絡也很常見。在金融和風控領域,商業關係實際上是很典型的一張圖,多個公司之間有貿易往來,公司和銀行之間也有往來。好比說一個公司去銀行申請貸null款的時候,銀行在審查這家公司可能自己沒有什麼問題,可是這家公司可能控制或者被控制的其餘公司,或者整個集團的其餘子公司,早已經進入了黑名單,甚至要控制一組相互擔保的公司之間的整體貸款額度。這個時候就須要構成一些風控的功能來拒掉這筆貸款。商業關係裏面還有人與人之間的轉帳關係,好比去查一個信用卡反套null現的網絡。很典型的一個網絡社羣就是:A 轉帳到 B,B 轉帳到 C,C 又轉讓回 A 就是一個很典型的一個環。更多的黑產可能會是一個很大的黑產社區。對於這樣的閉環,這類查詢在圖數據庫大規模應用以前,大部分都是採用離線計算的方式去找。可是離線場景很難去控制當前發生的這筆交易。例如一個信用卡交易或者在線貸null款,整個做業流程很長,在反套null現這塊的審覈時間可能只有秒級。這也是圖數據庫很是大的一個應用場景。架構
知識圖譜:除了商業關係還有一個就是知識圖譜。知識圖譜這個概念提出來已經很早了,大概是在 2004,2005 年的時候,Google 把本身的 search engine 慢慢的從倒排轉到知識圖譜上。這樣在 search 的時候能夠回答一些問題,好比說今天的天氣怎麼樣?好比說如今誰的老婆的外甥的二大爺是誰。根據一些相似於問題式的知識,而不是基於關鍵字進行 search。知識圖譜這幾年很是的火,主要的緣由就是一些垂直領域,慢慢的發現知識圖譜很是的有價值。好比說:在金融領域上會有本身金融領域的知識圖譜,結合一些 NLP 技術作大量的財報自動分析,或者像 Kensho 這樣的新聞事件驅動自動生成分析報表和投資建議;還能夠作一些投資組合,發現一二級市場公司內的關聯關係,財務造假或者地方債暴雷形成的風險傳播。再好比不少作在線教育的同事可能知道,在線教育的領域裏面也有很多知識圖譜。好比說有哪些考點,這個題是屬於哪些考點,考點之間是怎麼關聯起來的,作錯的考點附近的知識點都須要增強,這樣也是一張關係網絡。也是圖數據庫一個普遍應用的場景。
IoT 物聯網(Internet of Things)是目前很是火的。之前,每個設備都是單純的 Device,設備和設備之間是沒有關係的。可是,物聯網的出現打通了這些設備之間的關係。好比:帳號和設備都是有綁定關係的,帳號和帳號之間又有必定的關係,經過這樣設備之間也能夠創建出一張網絡來。
通常來講,圖數據庫並非簡單的關聯關係查詢,在圖遍歷的過程,一般要根據屬性作一些計算。因此一個單單的圖關聯是徹底不能知足要求的。舉個例子,這是一個股票新聞實時推薦的場景。
你們知道通常散戶炒股並非高頻這樣事件驅動的,可是他們也會邊看新聞邊盯着 K線。因此在這個時候要給他們推薦一些什麼新聞呢。通常常見的辦法是爬蟲得到新聞,清洗完畢後,NLP 分詞,提取出關鍵詞後,而後跟股票代碼關聯上。通常根據監管,可能還要加上一些編輯審覈和推送。但你們知道中國股市好的時候,是線下口口相傳的。因此有個思路是經過好友圈來推薦新聞:首先會去找用戶的好友,而後這些好友可能瀏覽過一些文章,那麼根據駐留時間等,好友對這個文章可能會有一個評分,這個評分用 WL 來表示。好友和好友之間也有必定的親密度,用 WC 表示。這個親密度能夠來源於以前的聊天次數、轉帳次數等。同一我的到一篇文章之間可能會有多條路徑。好比說到第二篇文章,可能會有幾十條路徑。因此說這麼多條路徑的權值之和表明了我和這篇文章的之間的評分。最終給用戶推薦文章的時候,但願是把全部的計算結果作 Top N。從線上的結果來看,轉化效率比其餘幾種都要高。
再回到技術底層,圖數據庫面臨的技術挑戰。
一個挑戰就是極低的 latency 和極高的 throughput。好比說查尋好友的好友這樣的兩跳場景,咱們的 Nebula Graph 能在十毫秒之內返回,同時能作到單機 10 萬的 pps。
另一個挑戰就是數據量。一個典型的銀行金融圖譜,數據量已經能夠達到百 T 規模,大概是幾十億個點和千億條邊的規模。固然,若是圖自己只是存點 ID 和點 ID 之間的關聯關係,這樣的數據量千億級別其實單機也能存儲。可是實際上就像剛纔說的,光純點和邊是不夠的,還須要有不少圖屬性作分析,這樣單機是確定不夠的。另外就是數據量增加的速度至關快,即便今天單機作個 POC 能存下,可能幾個月以後又要擴容了。
還有一個挑戰就是如今愈來愈複雜的商業邏輯,用傳統的數據庫去分析,基本上每個邏輯都要寫 Java 代碼來完成查詢數據。咱們但願不要那麼依賴於開發人員,分析人員能夠像寫 SQL 同樣,本身能夠搞定。
最後一個挑戰就是關於高可用要求。圖數據庫剛開始出現的時候,基本上就是一個二級索引。至關於只緩存了點和邊之間的關係,真正的屬性多是在別的地方(好比 HBase 或者 MySQL 裏面)。Data 自己的正確性和高可用都是都是依賴於這些組件的。但隨着使用場景愈來愈多,這樣分離的存儲方式性能跟不上,天然就但願數據直接放在圖數據庫裏面。那麼各類傳統數據庫和分佈式系統要面臨的技術問題也要解決。好比數據多副本的強一致性問題,ACID。對於圖數據庫的要求愈來愈多,客戶更但願做爲一個數據庫,而不是做爲一個索引或者關係 cache。
對於 Nebula Graph 來說,有這麼幾個技術特色:第一個就是採用了存儲計算分離的架構。這樣架構主要的考慮其實前面幾個 Talk你們都已經討論了不少,主要好處就是爲了上雲或者說 彈性
, 方便單獨擴容
。上午的 Talk:HBase on Cloud 也有提到,業務水位老是很難預測的,一段時間存儲不夠了,有些時候計算不夠了。在雲上或者使用容器技術,計算存儲分離的架構運維起來會比較方便,成本也更好控制。你們使用 HBase 那麼久,這方面的感觸確定不少。
Nebula Graph 的第二個技術特色是它的查詢語言,咱們稱爲 nGQL,比較接近 SQL。惟一大一點的語法差別就是 不用嵌套
(embedding)。你們都知道嵌套的 SQL,讀起來是很是痛苦的,要從裏向外讀。
第三個特色就是 Nebula Graph 支持多種後端存儲,除了原生的引擎外,也支持 HBase。由於不少用戶,對 HBase 已經至關熟悉了,並不但願多一套存儲架構。從架構上來講,Nebula Graph 是徹底對等的分佈式系統。
和 HBase 的 CoProcessor 同樣,Nebula Graph 支持數據計算下推。數據過濾,包括一些簡單的聚合運算,可以在存儲層就作掉,這樣對於性能來說能提高會很是大。
多租戶,Nebula Graph是經過多 Space 來實現的。Space 是物理隔離。
除了圖查詢外,還有很常見的一種場景是全局的屬性查詢。這個和 MySQL 同樣,要提高性能的主要辦法是爲 屬性創建索引
,這個也是 Nebula Graph 原生支持的功能。
最後的技術特色就是關於圖算法方面。這裏的算法和全圖計算不太同樣,更可能是一個子圖的計算,好比最短路徑。你們知道數據庫一般有 OLTP 和 OLAP 兩種差別很大的場景,固然如今有不少 HTAP 方面的努力。那對於圖數據庫來講也是相似,咱們在設計 Nebula Graph 的時候,作了一些權衡。咱們認爲全圖的計算,好比 Page Rank,LPA,它的技術挑戰和 OLTP 的挑戰和對應的設計相差很大。咱們但願 Nebula Graph 可以在 OLTP 這塊提供最好的表現。
下面爲你們介紹 Nebula Graph 的架構圖:下圖(圖1)是基於原生存儲的,圖3 是基於 HBase 的,有一些不一樣。
這條虛線上面是計算層,下面是存儲層。
圖 1:基於原生存儲的架構圖
咱們先看下計算層,計算層能夠理解爲把一個 query 翻譯成真正須要的執行計劃,產生執行計劃以後,到下面存儲層拿須要的數據。這和傳統數據庫很是相似,查詢語言也很相似。這裏面比較重要的事情是查詢優化,除了前面提到的計算下推到存儲層外,目前一個主要的實現是併發執行。
圖 2:Query Service
舉個例子,查好友的大於 18 歲的好友,可能好友有不少,沒有必要等一度好友都返回後,再去查二度好友。固然應該異步來作,一度好友部分返回後,就馬上開始二度查詢。有點相似圖計算裏面的 BSP 和 ASP。這個優化對提高性能有很是大做用。對於 Storage 層來講,又分爲上面的 Storage Engine 和 KV Store。由於 Nebula Graph 是分佈式系統,數據是分片的。目前的分片方法是靜態哈希,和 HBase 不同。主要是由於圖查詢基本都是特定 Prefix 的 Scan,Get 不多。好比一我的的好友這樣,就是同一個 prefix 的 scan。每個數據分片會經過 RAFT 協議來保證數據的強一致。這和 HBase 寫到底層 HDFS 也不同。3 臺機器上的 Partition1 組成一個 Raft Group。Storage Engine 作的事情比較簡單,就是把圖語義的查詢請求翻譯成 KV 的查詢請求。關於圖右邊的 Meta Service,它的主要做用是 schema 管理和集羣管理。Nebula Graph 中的點和邊都是有屬性和版本的,那每一個屬性的類型和版本在 MetaService 中統一管理。集羣管理主要用於運維和鑑權目的,負責機器上下線和對用戶作 ACL。
圖 3:基於 HBase 的架構圖
Nebula Graph 的 HBase 版本略微有些不同,能夠看到虛線往下挪了,Storage Service 嵌入到 Query Engine 裏面,這是由於 HBase 是獨立的服務,Storage Service 進程能夠和 Query Engine 放同一臺機器上,直接一對一服務了。另外,由於 HBase 本身有 partition,就不必再分一次了。
下面介紹下 Nebula Graph 的數據模型和 Schema(每種標籤有一組相對應的屬性,咱們稱之爲 schema)。前面說到 Nebula Graph 是有向屬性圖,點和邊都有各自屬性。點有點屬性,Nebula Graph 裏面稱爲 Tag(類型),點能夠有多種類型,或者叫多種 Tag。好比一個點既能夠是 Tag Person,有屬性姓名、年齡;也是 Tag developer,屬性是擅長的語言。Tag 是能夠像類同樣繼承的,一個 Tag 繼承自另一個 Tag。邊和點略微有點不同,一條邊只能有一種類型。可是兩個點之間能夠有多種類型的邊。另外,像 TTL 這種功能,Nebula Graph 也是支持的。Nebula Graph 的數據模型和 Schema!這裏須要提一下,對於 HBase 和 Nebula Graph 原生存儲來講,Schema Version 處理上是不同的。HBase 是沒有 Schema 的。
強 Schema 最大的好處,是知道這條數據何時結束的,一行有多少屬性是知道的。因此在根據某個版本號取數據的時候,從某一行跳到下一行,不須要對每一個屬性都掃描一遍。但若是像 HBase 這樣弱 Schema 系統,性能消耗是很是大。但相應的,問題就來了,若是要支持強 Schema,要變動 Schema 怎麼辦?更改 Schema 在 MySQL 裏面,每每要鎖表的。對於 Nebula Graph 來講,當更改 Schema 時,並非在原來的數據上進行更改,而是先插入一個新的 Schema,固然這要求寫入數據的時候就要記錄版本號。這樣的話在讀的時候,才能知道要用版本。
再解釋一下關於 Key 的設計,點和邊的 Key 設計是像上面兩行這樣,一個點是一個 Key,一條邊是兩個 Key,這樣的目的是把起點和出邊存在一塊兒,對端的終點和入邊存儲在一塊兒。這樣在查詢的時候,能夠減小一次網絡。另外,對於 Nebula Graph 原生存儲和 HBase 存儲,屬性採用的存儲方式也是不同的。在 HBase 裏面,一個屬性放在一個 Column 裏面。在原生存儲裏面,全部屬性放在一個 Column 裏面。這樣設計的主要緣由是,若是用戶使用 HBase 做爲底層存儲,其實他更指望 HBase 這張表在別的系統裏面也能夠用,因此說咱們考慮把它打散開了。
最後講一下咱們的 Query Language:nGQL
咱們說它比較相似 SQL,好比說看這個例子,從某一個點開始向外拓展,用 nGQL 來寫就是,GO FROM $id,起始點,而後 OVER edge,沿着某條邊,還能夠設置一些過濾條件,好比說,從這個點出發,沿着個人好友邊,而後去拿,裏面年齡大於十八歲的。
那要返回哪些屬性?能夠用 YIELD,好比說年齡,家庭住址。前面提到,不但願嵌套,嵌套太難讀了,因此做爲替代, Nebula Graph 用 PIPE 管道。前一條子查詢的結果,PIPE 給第二條,而後第二條能夠 PIPE 給第三條。這樣從前日後讀起來,和咱們人的思考順序是同樣的。可是管道只解決了一個輸入源的問題。
多個輸入源的時候怎麼辦?Nebula Graph 還支持定義某個變量,這個和存儲過程有點像。像上面這樣,把 $var 定義成一個子查詢的結果,再把這個結果拿去給其餘子查詢使用。還有種很常見的查詢是全局匹配,這個和 SQL 裏面的 SELECT … FROM … WHERE 同樣,它要找到全部知足條件的點或者邊。咱們這裏暫時取名叫作 FIND。你們要是以爲其餘名字好也能夠在 GitHub 上給咱們提 issue。
最後就是一些 UDF,用戶本身寫的函數,有些複雜的邏輯用 SQL 可能很差描述,Nebula Graph 也但願支持讓用戶本身寫一些代碼。由於咱們代碼是 C++ 寫的,再考慮到用戶羣體,作數據分析用 Python 比較多,咱們考慮先支持 C++ 和 Python。
現場參會者提問:大家這個架構是 TinkerPop 的實現嘛?區別在哪裏?
陳恆的回覆以下:
不是的。咱們是徹底自研的。
首先咱們查詢語法並非 Gremlin 那樣命令式的,而是更接近 SQL 這種描述式的。能夠說下咱們的思考,咱們主要考慮了查詢優化的問題。
你知道像 Gremlin 那樣的命令式語言,query 是 .in() .out() 這樣一步步組成的,因此查詢引擎只能按照給定的命令一步步把數據撈上來,每次序列化速度都很慢的,像 Titan 那樣。咱們的測試結果應該有幾十倍的性能差距。
另外既然用戶每步指令是明確的,查詢引擎要作優化很難,要很是智能推測出用戶整一串指令的最終指望才能優化,這樣難度比較高。這個有點像編譯器的優化,優化錯就很麻煩了。
咱們但願像 SQL 這樣描述式的,用戶說明最終目的就行,怎麼處理交給執行引擎來優化,這樣作優化比較容易完善,可借鑑的算法也比較多。
固然也和咱們以 C++ 作開發語言有關。咱們也有想過作 Gremlin 和 nGQL 之間的 driver,主要看社區,歡迎給咱們提 issue
上面就是本次 Nebula Graph 參會 HBaseCon Asia2019 的所有內容,最後和你們再說下 Nebula Graph 是徹底開源的項目,對於圖數據庫比較感興趣的同窗能夠加 wechat 討論羣,或者在 GitHub 上提 Issue,也歡迎你們給咱們支持 star 項目。
Nebula Graph:一個開源的分佈式圖數據庫。