美團圖數據庫平臺建設及業務實踐

圖數據結構,可以更好地表徵現實世界。美團業務相對較複雜,存在比較多的圖數據存儲及多跳查詢需求,亟需一種組件來對千億量級圖數據進行管理,海量圖數據的高效存儲和查詢是圖數據庫研究的核心課題。本文介紹了美團在圖數據庫選型及平臺建設方面的一些工做。

1 前言

圖數據結構,可以很天然地表徵現實世界。好比用戶、門店、騎手這些實體能夠用圖中的點來表示,用戶到門店的消費行爲、騎手給用戶的送餐行爲能夠用圖中的邊來表示。使用圖的方式對場景建模,便於描述複雜關係。在美團,也有比較多的圖數據存儲及多跳查詢需求,歸納起來主要包括如下 4 個方面:前端

  • 圖譜挖掘: 美團有美食圖譜、商品圖譜、旅遊圖譜、用戶全景圖譜在內的近 10 個領域知識圖譜,數據量級大概在千億級別。在迭代、挖掘數據的過程當中,須要一種組件對這些圖譜數據進行統一的管理。
  • 安全風控: 業務部門有內容風控的需求,但願在商戶、用戶、評論中經過多跳查詢來識別虛假評價;在支付時進行金融風控的驗證,實時多跳查詢風險點。
  • 鏈路分析: 包括代碼分析、服務治理、數據血緣管理,好比公司數據平臺上有不少 ETL Job,Job 和 Job 之間存在強弱依賴關係,這些強弱依賴關係造成了一張圖,在進行 ETL Job 的優化或者故障處理時,須要對這個圖進行實時查詢分析。
  • 組織架構: 公司組織架構的管理,實線彙報鏈、虛線彙報鏈、虛擬組織的管理,以及商家連鎖門店的管理。好比,維護一個商家在不一樣區域都有哪些門店,可以進行多層關係查找或者逆向關係搜索。

整體來講,美團須要一種組件來管理千億級別的圖數據,解決圖數據存儲以及多跳查詢問題。海量圖數據的高效存儲和查詢是圖數據庫研究的核心課題,如何在大規模分佈式場景中進行工程落地是咱們面臨的痛點問題。傳統的關係型數據庫、NoSQL 數據庫能夠用來存儲圖數據,可是不能很好處理圖上多跳查詢這一高頻的操做。git

Neo4j 公司在社交場景(見圖1)裏作了傳統關係型數據庫 MySQL 跟圖數據庫 Neo4j 的查詢性能對比 [1],在一個包含 100 萬人、每人約有 50 個朋友的社交網絡裏找最大深度爲 5 的朋友的朋友,實驗結果代表多跳查詢中圖數據庫優點明顯(見圖 2)。然而選取或者自主研發一款高吞吐、低查詢延時、能存儲海量數據且易用的圖數據庫很是困難。下面將介紹美團在圖數據庫選型及平臺建設方面的一些工做。github

圖 1

圖 2

2 圖數據庫選型

在圖數據庫的選型上咱們主要考慮瞭如下 5 點:(A) 項目開源,暫不考慮需付費的圖數據庫;(B) 分佈式架構設計,具有良好的可擴展性;(C) 毫秒級的多跳查詢延遲;(D) 支持千億量級點邊存儲;(E) 具有批量從數倉導入數據的能力。算法

分析 DB-Engines[2] 上排名前 30 的圖數據庫,剔除不開源的項目,咱們將剩餘的圖數據庫分爲三類:數據庫

  • 第一類:Neo4j[3]、ArangoDB[4]、Virtuoso[5]、TigerGraph[6]、RedisGraph[7]。 此類圖數據庫只有單機版本開源可用,性能優秀,但不能應對分佈式場景中數據的規模增加,即不知足選型要求(B)、(D)。
  • 第二類:JanusGraph[8]、HugeGraph[9]。 此類圖數據庫在現有存儲系統之上新增了通用的圖語義解釋層,圖語義層提供了圖遍歷的能力,可是受到存儲層或者架構限制,不支持完整的計算下推,多跳遍歷的性能較差,很難知足 OLTP 場景下對低延時的要求,即不知足選型要求(C)。
  • 第三類:DGraph[10]、NebulaGraph[11]。 此類圖數據庫根據圖數據的特色對數據存儲模型、點邊分佈、執行引擎進行了全新設計,對圖的多跳遍歷進行了深度優化,基本知足咱們的選型要求。

DGraph 是由前 Google 員工 Manish Rai Jain 離職創業後,在 2016 年推出的圖數據庫產品,底層數據模型是 RDF[12],基於 Go 語言編寫,存儲引擎基於 BadgerDB[13] 改造,使用 RAFT 保證數據讀寫的強一致性。後端

NebulaGraph 是由前 Facebook 員工葉小萌離職創業後,在 2019年 推出的圖數據庫產品,底層數據模型是屬性圖,基於 C++ 語言編寫,存儲引擎基於 RocksDB[14] 改造,使用 RAFT 保證數據讀寫的強一致性。安全

這兩個項目的創始人都在互聯網公司圖數據庫領域深耕多年,對圖數據庫的落地痛點有深入認識,總體的架構設計也有較多類似之處。在圖數據庫最終的選型上,咱們基於 LDBC-SNB 數據集[15]對 NebulaGraph、DGraph、HugeGraph 進行了深度性能測評,測試詳情見文章:主流開源分佈式圖數據庫 Benchmark,從測試結果看 NebulaGraph 在數據導入、實時寫入及多跳查詢方面性能均優於競品。此外,NebulaGraph 社區活躍,問題響應速度快,因此團隊最終選擇基於 NebulaGraph 來搭建圖數據庫平臺。網絡

3 NebulaGraph架構

圖 3

一個完整的 NebulaGraph 集羣包含三類服務,即 Query Service、Storage Service 和 Meta Service。每類服務都有其各自的可執行二進制文件,既能夠部署在同一節點上,也能夠部署在不一樣的節點上。下面是NebulaGraph 架構設計(見圖 3)的幾個核心點16。數據結構

  • Meta Service: 架構圖中右側爲 Meta Service 集羣,它採用 Leader/Follower 架構。Leader 由集羣中全部的 Meta Service 節點選出,而後對外提供服務;Followers 處於待命狀態,並從 Leader 複製更新的數據。一旦 Leader 節點 Down 掉,會再選舉其中一個 Follower 成爲新的 Leader。Meta Service 不只負責存儲和提供圖數據的 Meta 信息,如 Schema、數據分片信息等;同時還提供 Job Manager 機制管理長耗時任務,負責指揮數據遷移、Leader 變動、數據 compaction、索引重建等運維操做。
  • 存儲計算分離: 在架構圖中 Meta Service 的左側,爲 NebulaGraph 的主要服務,NebulaGraph 採用存儲與計算分離的架構,虛線以上爲計算,如下爲存儲。存儲計算分離有諸多優點,最直接的優點就是,計算層和存儲層能夠根據各自的狀況彈性擴容、縮容。存儲計算分離還帶來了另外一個優點:使水平擴展成爲可能。此外,存儲計算分離使得 Storage Service 能夠爲多種類型的計算層或者計算引擎提供服務。當前 Query Service 是一個高優先級的 OLTP 計算層,而各類 OLAP 迭代計算框架會是另一個計算層。
  • 無狀態計算層: 每一個計算節點都運行着一個無狀態的查詢計算引擎,而節點彼此間無任何通訊關係。計算節點僅從 Meta Service 讀取 Meta 信息以及和 Storage Service 進行交互。這樣設計使得計算層集羣更容易使用 K8s 管理或部署在雲上。每一個查詢計算引擎都能接收客戶端的請求,解析查詢語句,生成抽象語法樹(AST)並將 AST 傳遞給執行計劃器和優化器,最後再交由執行器執行。
  • Shared-nothing 分佈式存儲層: Storage Service 採用 Shared-nothing 的分佈式架構設計,共有三層,最底層是 Store Engine,它是一個單機版 Local Store Engine,提供了對本地數據的get/put/scan/delete 操做,該層定義了數據操做接口,用戶能夠根據本身的需求定製開發相關 Local Store Plugin。目前,NebulaGraph 提供了基於 RocksDB 實現的 Store Engine。在 Local Store Engine 之上是 Consensus 層,實現了 Multi Group Raft,每個 Partition 都對應了一組 Raft Group。在 Consensus 層上面是 Storage interfaces,這一層定義了一系列和圖相關的 API。 這些 API 請求會在這一層被翻譯成一組針對相應 Partition 的 KV 操做。正是這一層的存在,使得存儲服務變成了真正的圖存儲。不然,Storage Service 只是一個 KV 存儲罷了。而 NebulaGraph 沒把 KV 做爲一個服務單獨提出,最主要的緣由即是圖查詢過程當中會涉及到大量計算,這些計算每每須要使用圖的 Schema,而 KV 層沒有數據 Schema 概念,這樣設計比較容易實現計算下推,是 NebulaGraph 查詢性能優越的主要緣由。

NebulaGraph 基於 C++ 實現,架構設計支持存儲千億頂點、萬億邊,並提供毫秒級別的查詢延時。咱們在 3 臺 48U192G 物理機搭建的集羣上灌入 10 億美食圖譜數據對 NebulaGraph 的功能進行了驗證。架構

  • 一跳查詢 TP99 延時在 5ms 內,兩跳查詢 TP99 延時在 20ms 內,通常的多跳查詢 TP99 延時在百毫秒內。
  • 集羣在線寫入速率約爲20萬 Records/s。
  • 支持經過 Spark 任務離線生成 RocksDB 底層 SST File,直接將數據文件載入到集羣中,即相似 HBase BulkLoad 能力。
  • 提供了類 SQL 查詢語言,對於新增的業務需求,只需構造 NebulaGraph SQL 語句,易於理解且能知足各種複雜查詢要求。
  • 提供聯合索引、GEO 索引,可經過實體屬性或者關係屬性查詢實體、關係,或者查詢在某個經緯度附近 N 米內的實體。
  • 一個 NebulaGraph 集羣中能夠建立多個 Space (概念相似 MySQL 的DataBase),而且不一樣 Space 中的數據在物理上是隔離的。

4 圖數據庫平臺建設

圖 4

爲了統一管理圖數據,減小工程同窗在圖數據庫集羣上的運維壓力,咱們基於開源分佈式圖數據庫 NebulaGraph,搭建了一套一站式圖數據庫自助管理平臺(見圖 4),該平臺包含如下 4 層:

  • 數據應用層。 業務方能夠在業務服務中引入圖譜 SDK,實時地對圖數據進行增刪改查。
  • 數據存儲層。 支持兩種圖數據庫集羣的部署。

    • 第一種部署方式是 CP 方案,即 Consistency & Partition tolerance。單集羣部署,集羣中機器數量大於等於副本的數量,副本數量大於等於 3 。只要集羣中有大於副本數一半的機器存活,整個集羣就能夠對外正常提供服務。CP 方案保證了數據讀寫的強一致性,但這種部署方式下集羣可用性不高。
    • 第二種部署方式是 AP 方案,即 Availability & Partition tolerance。在一個應用中部署多個圖數據庫集羣,每一個集羣數據副本數爲 1 ,多集羣之間進行互備。這種部署方式的好處在於整個應用對外的可用性高,但數據讀寫的一致性要差些。
  • 數據生產層。 圖數據主要有兩種來源,第一種是業務方把數倉中數據經過 ETL Job 轉成點和邊的 Hive 表,而後離線導入到圖數據庫中;第二種是業務線上實時產生的數據、或者經過 Spark/Flink 等流式處理產生的近線數據,調用在線批量寫接口實時灌到圖數據庫中。
  • 支撐平臺。 提供了 Schema 管理、權限管理、數據質檢、數據增刪改查、集羣擴縮容、圖譜畫像、圖數據導出、監控報警、圖可視化、集羣包管理等功能。

與業界方案相比,團隊主導設計的圖數據庫平臺除了支持存儲千億頂點、萬億邊,具有毫秒級別查詢能力外,還提供了以下四項能力:應用可用性 SLA 達 99.99%;支持每小時百億量級數據導入;實時寫入數據時保證多集羣數據最終一致性;易用的圖譜可視化能力。下面將介紹具體的設計思路。

4.1 高可用模塊設計

圖 5

首先介紹單應用多集羣高可用模塊的設計(AP 方案)。爲何有 AP 方案的設計呢?由於接入圖數據庫平臺的業務方比較在乎的指標是集羣可用性。在線服務對集羣的可用性要求很是高,最基礎的要求是集羣可用性能達到 4 個 9,即一年裏集羣的不可用時間要小於一個小時。對於在線服務來講,服務或者集羣的可用性是整個業務的生命線,若是這點保證不了,即便集羣提供的能力再多再豐富,那麼業務方也不會考慮使用,可用性是業務選型的基礎。

另外,公司要求中間件要有跨區域容災能力,即要具有在多個地域部署多集羣的能力。咱們分析了平臺接入方的業務需求,大約 80% 的場景是 T+1 全量導入數據、線上只讀。在這種場景下,對圖數據的讀寫強一致性要求並不高,所以咱們設計了單應用多集羣這種部署方案。

AP 方案部署方式能夠參考圖 5,一個業務方在圖數據庫平臺上建立了 1 個應用並部署了 4 個集羣,其中北京 2 個、上海 2 個,平時這 4 個集羣同時對外提供服務。假如如今北京集羣 1 掛了,那麼北京集羣 2 能夠提供服務。若是說真那麼不巧,北京集羣都掛了,或者北京側對外的網絡不可用,那麼上海的集羣也能夠提供服務。在這種部署方式下,平臺會盡量地經過一些方式來保證整個應用的可用性。而後每一個集羣內部儘可能部署同機房的機器,由於圖數據庫集羣內部 RPC 很是多,若是有跨機房或者跨區域的頻繁調用,整個集羣對外的性能會比較低。

圖 6

高可用模塊主要包含下面 4 個部分,如上圖 6 所示:

第一部分是右側的圖數據庫 Agent,它是部署在圖數據庫集羣的一個進程,用來收集機器和圖數據庫三個核心模塊的信息,並上報到圖數據庫平臺。Agent 可以接收圖數據庫平臺的命令並對圖數據庫進行操做。

第二部分是圖數據庫平臺,它主要是對集羣進行管理,並同步圖數據庫集羣的狀態到配置中心。

第三部分是圖數據庫 SDK,主要負責管理鏈接到圖數據庫集羣的鏈接。若是業務方發送了某個查詢請求,SDK 會進行集羣的路由和負載均衡,選擇出一條高質量的鏈接來發送請求。此外,SDK 還會處理圖數據庫集羣中問題機器的自動降級以及恢復,而且支持平滑切換集羣的數據版本。

第四部分是配置中心,相似 ZooKeeper,存儲集羣的當前狀態。

4.2 每小時百億量級數據導入模塊設計

圖 7

第二個模塊是每小時百億量級數據導入模塊,平臺在 2019 年末- 2020 年初全量導入數據的方式是調用 NebulaGraph 對外提供的批量數據導入接口,這種方式的數據寫入速率大概是每小時 10 億級別,導入百億數據大概要耗費 10 個小時,耗時較長。此外,在以幾十萬每秒的速度導數據的過程當中,會長期佔用機器的 CPU、IO 資源,一方面會對機器形成損耗,另外一方面數據導入過程當中集羣對外提供的讀性能會變弱。

爲了解決上面兩個問題,平臺進行了以下優化:在 Spark 集羣中直接生成圖數據庫底層文件 SST File,再借助 RocksDB 的 Bulkload 功能直接 ingest 文件到圖數據庫。

數據導入的核心流程能夠參考圖 7,當用戶執行導數據操做後,圖數據庫平臺會向公司的 Spark 集羣提交一個 Spark 任務,在 Spark 任務中會生成圖數據庫裏相關的點、邊以及點索引、邊索引相關的 SST 文件,並上傳到美團的 S3 雲存儲上。文件生成後,圖數據庫平臺會通知應用中多個集羣去下載這些存儲文件,以後完成 ingest 跟 compact 操做,最後完成數據版本的切換。

爲兼顧各個業務方的不一樣需求,平臺統一了應用導入、集羣導入、離線導入、在線導入,以及全量導入、增量導入這些場景,而後細分紅下面九個階段,從流程上保證在導數據過程當中應用總體的可用性:SST File 生成 、SST File 下載 、ingest、compact、數據校驗、增量回溯、數據版本切換、集羣重啓、數據預熱。

4.3 實時寫入多集羣數據同步模塊設計

圖 8

第三個模塊是實時寫入多集羣數據同步模塊,平臺約有 15% 的需求場景是在實時讀取數據時,還要把新產生的業務數據實時寫入集羣,而且對數據的讀寫強一致性要求不高。就是說,業務方寫到圖數據庫裏的數據,不須要立馬能讀到。針對上述場景,業務方在使用單應用多集羣這種部署方案時,多集羣裏的數據須要保證最終一致性。針對這一需求,咱們作了如下設計。

第一部分是引入 Kafka 組件,業務方在服務中經過 SDK 對圖數據庫進行寫操做時,SDK 並不直接寫圖數據庫,而是把寫操做寫到 Kafka 隊列裏,以後由該應用下的多個集羣異步消費這個 Kafka 隊列。

第二部分是集羣在應用級別可配置消費併發度,來控制數據寫入集羣的速度。具體流程以下:

  • SDK 對用戶寫操做語句作語法解析,將其中點邊的批量操做拆解成單個點邊操做,即對寫語句作一次改寫。
  • Agent 消費 Kafka 時確保每一個點及其出邊相關操做在單個線程裏順序執行(見圖 8),保證這點就能保證各個集羣執行完寫操做後最終的結果是一致的。
  • 併發擴展:經過改變 Kafka 分片數、Agent 中消費 Kafka 線程數來調整 Kafka 中操做的消費速度。若是將來圖數據庫支持事務的話,上面的配置須要調整成單分片單線程消費,有必要對設計方案再作優化調整。

圖 9

第三部分是在實時寫入數據過程當中,平臺能夠同步生成一個全量數據版本,並作平滑切換(見圖 9),確保數據的不重、不漏、不延遲。

4.4 圖可視化模塊設計

圖 10

第四個模塊是圖可視化模塊(見圖10),主要是用於解決子圖探索問題。當用戶在圖數據庫平臺經過可視化組件查看圖數據時,能儘可能經過恰當的交互設計來避免由於節點過多而引起爆屏。主要包括如下幾個功能:

  • 經過 ID 或者索引查找頂點。
  • 能查看頂點和邊的卡片(卡片中展現點邊屬性和屬性值),能夠單選、多選、框選以及按類型選擇頂點。
  • 圖探索,當用戶點擊某個頂點時,系統會展現它的一跳鄰居信息,包括該頂點有哪些出邊?經過這個邊它能關聯到幾個點?該頂點的入邊又是什麼狀況?經過這種一跳信息的展現,用戶在平臺上探索子圖的時候,可快速瞭解到周邊的鄰居信息,更快地進行子圖探索。在探索過程當中,平臺也支持經過屬性對邊進行過濾。
  • 圖編輯能力,讓平臺用戶在不熟悉 NebulaGraph 語法的狀況下也能增刪改點邊數據,對線上數據進行臨時干預。

5 業務實踐

5.1 智能助理

該項目數據是基於美團商戶數據、用戶評論構建的餐飲娛樂知識圖譜,覆蓋美食、酒店、旅遊等領域,包含 13 類實體和 22 類關係。目前,點邊數量大概在百億級別,數據 T+1 全量更新,主要用於解決搜索或者智能助理裏 KBQA(全稱:Knowledge Based Question Answer)類問題。核心處理流程是經過 NLP 算法識別關係和實體後構造出 NebulaGraph SQL 語句,再到圖數據庫獲取數據。

典型的應用場景包括商場找店,好比,某個用戶想知道望京新薈城這個商場有沒有海底撈,系統能夠快速查出結果告訴用戶;另外一個場景是標籤找店,用戶想知道望京 SOHO 附近有沒有適合情侶約會的餐廳,或者能夠多加幾個場景標籤,系統均可以幫忙查找出來。

5.2 搜索召回

該項目數據是基於醫美商家信息構建的醫美知識圖譜,包含 9 類實體和 13 類關係,點邊數量在百萬級別,一樣也是 T+1 全量更新,主要用於大搜底層實時召回,返回與 Query 相關的商戶、產品或醫生信息,解決醫美類搜索詞少結果、無結果問題。好比,某個用戶搜「啤酒肚」這種症狀、或者「潤百顏」這類品牌,系統能夠召回相關的醫美門店。

5.3 圖譜推薦理由

該項目數據來自用戶的畫像信息、商戶的特徵信息、用戶半年內收藏/購買行爲,數據量級是 10 億級別,T+1 全量更新。如今美團 App 和點評 App 上默認的商戶推薦列表是由深度學習模型生成的,但模型並不會給出生成這個列表的理由,缺乏可解釋性。

而在圖譜裏用戶跟商戶之間自然存在多條連通路徑,項目考慮選出一條合適路徑來生成推薦理由,在 App 界面上展現給用戶推薦某家店的緣由。該項目基於用戶的協同過濾算法來生成推薦理由,在家鄉、消費水平、偏好類目、偏好菜系等多個組合維度中找出多條路徑,而後給這些路徑打分,選出一條分值較高的路徑,以後按照特定 Pattern 產出推薦理由。經過上述方式,就能夠得到「在北京喜歡北京菜的山東老鄉都說這家店很贊」,或者「廣州老鄉都中意他家的正宗北京炸醬麪」這類理由。

5.4 代碼依賴分析

該項目把代碼庫中代碼依賴關係寫入到圖數據庫。代碼庫中存在不少服務代碼,這些服務會包括對外提供的接口,這些接口的實現依賴於該服務中某些類的成員函數,這些類的成員函數又依賴了本類的成員變量、成員函數或者其它類的成員函數,那麼它們之間的依賴關係就造成了一張圖,能夠把這個圖寫到圖數據庫裏作代碼依賴分析。

典型應用場景是精準測試:當開發同窗完成需求並向公司的代碼倉庫提交了 PR 後,能夠把更改實時地寫到圖數據庫中。這樣的話,開發同窗就能查到他所寫的代碼影響了哪些外部接口,而且藉助圖可視化組件查看調用路徑。若是開發同窗原本是要改接口 A 的行爲,改了不少代碼,可是他可能並不知道他改的代碼也會影響到對外接口 B、C、D,這時候就能夠用代碼依賴分析來作個 Check,增長測試的完備性。

6 總結與展望

目前,圖數據庫平臺基本具有了對圖數據的一站式自助管理功能。若是某個業務方要使用這種圖數據庫能力,那麼業務方能夠在平臺上自助地建立圖數據庫集羣、建立圖的 Schema、導入圖數據、配置導入數據的執行計劃、引入平臺提供的 SDK 對數據進行操做等等。平臺側主要負責各業務方圖數據庫集羣的穩定性。目前,美團有三四十個業務已經在平臺上落地,基本知足了各個業務方的需求。

將來規劃主要有兩個方向,第一,根據業務場景優化圖數據庫內核,提高平臺穩定性,開發的通用 Feature 持續反哺 NebulaGraph 社區。第二,挖掘更多的圖數據價值。如今平臺僅支持圖數據存儲及多跳查詢這種基本能力,後續將基於 NebulaGraph 去探索圖學習、圖計算的能力,爲平臺用戶提供更多挖掘圖數據價值的功能。

7 做者信息

登昌、梁帥、高辰、楊鑫、尊遠、王超等,均爲美團搜索與NLP部工程師。

8 招聘信息

若是你對「圖存儲」、「圖學習」、「圖計算」感興趣,歡迎給咱們投遞簡歷,投遞郵箱:zhaodengchang@meituan.com。

9 參考資料

閱讀美團技術團隊更多技術文章合集

前端 | 算法 | 後端 | 數據 | 安全 | 運維 | iOS | Android | 測試

| 在公衆號菜單欄對話框回覆【2020年貨】、【2019年貨】、【2018年貨】、【2017年貨】等關鍵詞,可查看美團技術團隊歷年技術文章合集。

| 本文系美團技術團隊出品,著做權歸屬美團。歡迎出於分享和交流等非商業目的轉載或使用本文內容,敬請註明「內容轉載自美團技術團隊」。本文未經許可,不得進行商業性轉載或者使用。任何商用行爲,請發送郵件至tech@meituan.com申請受權。

相關文章
相關標籤/搜索