本文由合合信息大数据团队柳佳浩撰写
1.前言
图谱业务随着时间的推移愈发的复杂化,逐渐体现出了性能上的瓶颈:单机不足以支持更大的图谱。然而,从性能上来看,Neo4j 的原生图存储有着不可替代的性能优点,这一点是以前调研的 JanusGraph、Dgraph 等都难以逾越的鸿沟。即便 JanusGraph 在 OLAP 上面很是出色,对 OLTP 也有必定的支持,可是 GraphFrame 等也足以支撑其 OLAP 需求,更况且在 Spark 3.0 会提供 Cypher 支持的状况下,图谱的 OLAP 需求相比 OLTP 有更多途径能够解决。这个时候,Nebula Graph 的“横空出世”无疑是对分布式 OLTP 效率低下现状的一种突破。java
以前在各种调研、部署后,特别是从 JanusGraph 的 OLTP 效率最终测试发现没法知足线上需求以后,咱们再也不对同一图谱能够同时进行 OLAP 和 OLTP 进行强制性要求,而 Nebula Graph 的架构恰好符合图谱方面的须要:python
- 分布式——shared-nothing 分布式架构
- 高速 OLTP(性能须要和 Neo4j 相近)——Nebula Graph 的存储层架构查询直接映射物理地址,实际上能够算是原生图存储
- 服务的高可用(即在非人为状况下,图谱能够稳定提供服务)——局部失败服务可用、有快照机制
- 保证可扩展性——支持线性扩容,因为开源、支持二次开发
综上所述,Nebula Graph 架构上符合实际生产需求,所以对 Nebula Graph 进行了调研、部署、测试。关于部署、性能测试(美团 NLP 团队性能测试、腾讯云安全团队性能测试)的部分不管是官网仍是其余同窗在博客中都有比较详尽的数据,本文主要从 Spark 导入出发,算是对 Nebula Graph 对 Spark 的支持进行粗浅的理解。git
2.测试环境
- Nebula Graph 集群
- 3 台 32 c(实际限制了16 c)
- 400 G 内存(实际配置了 100 G)
- SSD
- 版本信息:Nebula Graph 版本 1.0.0(当时测试比较早)。
- 网络环境:万兆。
- 图谱大小:十亿级别节点(属性较少),百亿级别边(有向,无属性或带权值)。
- Spark 集群
- 版本信息:Spark 2.1.0
实际上 Nebula Graph 的使用资源合计 2T 左右 memory (3 * 30 executor + 1 driver) * 25G。github
3.Spark 批量导入
3.1 基础流程
- 打包 sst.generator(Spark 生成 sst 所须要的包)。
- 配置 Nebula Graph 集群,Nebula Graph 集群正常启动,建立图谱。
- Spark 配置文件
config.conf
(能够参考文档《Spark 导入工具》)进行配置。 - 排查 Spark 集群是否存在冲突的包。
- Spark 启动时使用配置文件和
sst.generator
快乐地导入。 - 数据校验。
3.2 一些细节
- 批量导入前推荐先创建索引。
这里推荐先创建索引的缘由是:批量导入仅在非线上图谱进行,虽然创建索引能够选择是否在提供服务的同时进行,可是为了防止后续 REBUILD
出现问题,这边能够优先建好索引。带来的问题就是在批量导入结点时相对较慢。算法
-
推荐用 int 型节点 ID(可使用 Snowflake算法 等),若是节点的 ID 不是 int 型,这里能够经过在节点/边中加入
policy: "uuid"
来设置自动生成 uuid。json -
若是使用的是单独的 Spark 集群可能不会出现 Spark 集群有冲突包的问题,该问题主要是 sst.generator 中存在可能和 Spark 环境内的其余包产生冲突,解决方法是 shade 掉这些冲突的包,或者更名。安全
-
Spark 调优方面:能够根据实际状况调整参数,尽可能下降 memory 以节约资源,相对的能够适当提升并行度加速。网络
3.3 导入结果
十亿级别节点(属性较少),百亿级别边(有向,无属性或带权值),提早建好索引的状况下大约消耗 20 小时左右导入全图。架构
3.4 关于 PR
由于在较早的版本使用了 Spark 导入,天然也有一些不太完善的地方,这边也提出了一些拙见,对 SparkClientGenerator.scala 略做了修改。分布式
- 最先在使用 Spark Writer(现:Exchange) 写入 Nebula Graph 时,发现错列的问题。
经过看源码发现 SparkClientGenerator.scala 存在 BUG,读取的是配置文件的位置而非 parquet/json
文件的位置,修复后提了我第一个 PR#2187,有幸经过
- 后续发现使用 SparkClientGenerator 自动生成 uuid/hash 功能时,存在会出现重复的双引号的问题,致使没法导入。
这块能够说是因为解决问题的想法不一样,提交了好屡次。重复引号的问题归根结底是对类型转化的时候添加了一次双引号,我这边发现有个 extraIndexValue 的方法能够把用户自填的非 string 类型的转成 string 类型,我这边想着可能会有用户想把非 string 型的 index 转成 uuid/hash(好比 array),因此修改的比较多。
可是和官方 @darionyaphet 沟通后,发现我这种作法实际上是对数据源进行了修改,用户传 array 等不支持的类型时,应该报错而不是转换类型(这个确实,一开始只考虑到了逻辑上跑通以及本身这边业务的使用,没考虑通用性)。从新修改,提交 PR #2258,经过。通过此次 PR 我也学到了不少。
- 以后发现 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,期待你来现场交流技术 😊