在 Spark 數據導入中的一些實踐細節


best-practices-import-data-spark-nebula-graph

本文由合合信息大數據團隊柳佳浩撰寫

1.前言

圖譜業務隨着時間的推移愈發的復雜化,逐漸體現出了性能上的瓶頸:單機不足以支持更大的圖譜。然而,從性能上來看,Neo4j 的原生圖存儲有着不可替代的性能優勢,這一點是之前調研的 JanusGraph、Dgraph 等都難以逾越的鴻溝。即使 JanusGraph 在 OLAP 上面非常出色,對 OLTP 也有一定的支持,但是 GraphFrame 等也足以支撐其 OLAP 需求,更何況在 Spark 3.0 會提供 Cypher 支持的情況下,圖譜的 OLAP 需求相比 OLTP 有更多途徑可以解決。這個時候,Nebula Graph 的“橫空出世”無疑是對分布式 OLTP 效率低下現狀的一種突破。

之前在各類調研、部署后,特別是從 JanusGraph 的 OLTP 效率最終測試發現無法滿足線上需求之后,我們不再對同一圖譜可以同時進行 OLAP 和 OLTP 進行強制性要求,而 Nebula Graph 的架構剛好符合圖譜方面的需要:

  1. 分布式——shared-nothing 分布式架構
  2. 高速 OLTP(性能需要和 Neo4j 相近)——Nebula Graph 的存儲層架構查詢直接映射物理地址,實際上可以算是原生圖存儲
  3. 服務的高可用(即在非人為情況下,圖譜可以穩定提供服務)——局部失敗服務可用、有快照機制
  4. 保證可擴展性——支持線性擴容,由於開源、支持二次開發

綜上所述,Nebula Graph 架構上符合實際生產需求,因此對 Nebula Graph 進行了調研、部署、測試。關於部署、性能測試(美團 NLP 團隊性能測試騰訊雲安全團隊性能測試)的部分無論是官網還是其他同學在博客中都有比較詳盡的數據,本文主要從 Spark 導入出發,算是對 Nebula Graph 對 Spark 的支持進行粗淺的理解。

2.測試環境

  1. Nebula Graph 集群
    1. 3 台 32 c(實際限制了16 c)
    2. 400 G 內存(實際配置了 100 G)
    3. SSD
    4. 版本信息:Nebula Graph 版本 1.0.0(當時測試比較早)。
  2. 網絡環境:萬兆。
  3. 圖譜大小:十億級別節點(屬性較少),百億級別邊(有向,無屬性或帶權值)。
  4. Spark 集群
    1. 版本信息:Spark 2.1.0

實際上 Nebula Graph 的使用資源合計 2T 左右 memory (3 * 30 executor + 1 driver) * 25G。

3.Spark 批量導入

3.1 基礎流程

  1. 打包 sst.generator(Spark 生成 sst 所需要的包)。
  2. 配置 Nebula Graph 集群,Nebula Graph 集群正常啟動,創建圖譜。
  3. Spark 配置文件 config.conf(可以參考文檔《Spark 導入工具》)進行配置。
  4. 排查 Spark 集群是否存在沖突的包。
  5. Spark 啟動時使用配置文件和 sst.generator 快樂地導入。
  6. 數據校驗。

3.2 一些細節

  1. 批量導入前推薦先建立索引

這里推薦先建立索引的原因是:批量導入僅在非線上圖譜進行,雖然建立索引可以選擇是否在提供服務的同時進行,但是為了防止后續 REBUILD 出現問題,這邊可以優先建好索引。帶來的問題就是在批量導入結點時相對較慢。

  1. 推薦用 int 型節點 ID(可以使用 Snowflake算法 等),如果節點的 ID 不是 int 型,這里可以通過在節點/邊中加入 policy: "uuid" 來設置自動生成 uuid。

  2. 如果使用的是單獨的 Spark 集群可能不會出現 Spark 集群有沖突包的問題,該問題主要是 sst.generator 中存在可能和 Spark 環境內的其他包產生沖突,解決方法是 shade 掉這些沖突的包,或者改名。

  3. Spark 調優方面:可以根據實際情況調整參數,盡量降低 memory 以節約資源,相對的可以適當提高並行度加速。

3.3 導入結果

十億級別節點(屬性較少),百億級別邊(有向,無屬性或帶權值),提前建好索引的情況下大約消耗 20 小時左右導入全圖。

3.4 關於 PR

因為在較早的版本使用了 Spark 導入,自然也有一些不太完善的地方,這邊也提出了一些拙見,對 SparkClientGenerator.scala 略作了修改。

  1. 最早在使用 Spark Writer(現:Exchange) 寫入 Nebula Graph 時,發現錯列的問題。

通過看源碼發現 SparkClientGenerator.scala 存在 BUG,讀取的是配置文件的位置而非 parquet/json 文件的位置,修復后提了我第一個 PR#2187,有幸通過

  1. 后續發現使用 SparkClientGenerator 自動生成 uuid/hash 功能時,存在會出現重復的雙引號的問題,導致無法導入。

這塊可以說是由於解決問題的想法不同,提交了好多次。重復引號的問題歸根結底是對類型轉化的時候添加了一次雙引號,我這邊發現有個 extraIndexValue 的方法可以把用戶自填的非 string 類型的轉成 string 類型,我這邊想着可能會有用戶想把非 string 型的 index 轉成 uuid/hash(比如 array),所以修改的比較多。

但是和官方 @darionyaphet 溝通后,發現我這種做法其實是對數據源進行了修改,用戶傳 array 等不支持的類型時,應該報錯而不是轉換類型(這個確實,一開始只考慮到了邏輯上跑通以及自己這邊業務的使用,沒考慮通用性)。重新修改,提交 PR #2258,通過。經過這次 PR 我也學到了很多。

  1. 之后發現 nebula-python 也有和官方 thrift 沖突的問題,本來想 shade 后提 PR,但是覺得這個改動太大了,所以直接提給官方,近期也修復了。

Nebula Graph 旁白:歡迎社區小伙伴來 GitHub 給我們提 PR,GitHub 傳送門:https://github.com/vesoft-inc/nebula/issues

4.總結 & 展望

因為之前調研過 JanusGraph,Nebula Graph 給我的第一印象就是:暗坑相對較少、社區反饋非常及時。在測試后 Nebula Graph 又用她的效率證明了自己,成為了分布式圖譜的首選項。

Nebula Graph 社區、群組、PR 官方反饋非常及時,這是圖譜迅速、茁壯成長的不可替代的重要因素,也希望可以后續可以繼續見證 Nebula Graph 的成長,繼續為 Nebula Graph 生態的完善添磚加瓦!

喜歡這篇文章?來來來,給我們的 GitHub 點個 star 表鼓勵啦~~ 🙇‍♂️🙇‍♀️ [手動跪謝]

Nebula Graph Meetup 深圳場報名中:https://www.huodongxing.com/event/4572357498700,期待你來現場交流技術 😊

best-practices-import-data-spark-nebula-graph


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM