在 Spark 数据导入中的一些实践细节

本文由合合信息大数据团队柳佳浩撰写
1.前言
图谱业务随着时间的推移愈发的复杂化,逐渐体现出了性能上的瓶颈:单机不足以支持更大的图谱。然而,从性能上来看,Neo4j 的原生图存储有着不可替代的性能优势,这一点是之前调研的 JanusGraph、Dgraph 等都难以逾越的鸿沟。即使 JanusGraph 在 OLAP 上面非常出色,对 OLTP 也有一定的支持,但是 GraphFrame 等也足以支撑其 OLAP 需求,更何况在 Spark 3.0 会提供 Cypher 支持的情况下,图谱的 OLAP 需求相比 OLTP 有更多途径可以解决。这个时候,Nebula Graph 的“横空出世”无疑是对分布式 OLTP 效率低下现状的一种突破。
之前在各类调研、部署后,特别是从 JanusGraph 的 OLTP 效率最终测试发现无法满足线上需求之后,我们不再对同一图谱可以同时进行 OLAP 和 OLTP 进行强制性要求,而 Nebula Graph 的架构刚好符合图谱方面的需要:
- 分布式——shared-nothing 分布式架构
- 高速 OLTP(性能需要和 Neo4j 相近)——Nebula Graph 的存储层架构查询直接映射物理地址,实际上可以算是原生图存储
- 服务的高可用(即在非人为情况下,图谱可以稳定提供服务)——局部失败服务可用、有快照机制
- 保证可扩展性——支持线性扩容,由于开源、支持二次开发
综上所述,Nebula Graph 架构上符合实际生产需求,因此对 Nebula Graph 进行了调研、部署、测试。关于部署、性能测试(美团 NLP 团队性能测试、腾讯云安全团队性能测试)的部分无论是官网还是其他同学在博客中都有比较详尽的数据,本文主要从 Spark 导入出发,算是对 Nebula Graph 对 Spark 的支持进行粗浅的理解。
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。
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。如果使用的是单独的 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,期待你来现场交流技术

在 Spark 数据导入中的一些实践细节的更多相关文章
- Nebula Exchange 工具 Hive 数据导入的踩坑之旅
摘要:本文由社区用户 xrfinbj 贡献,主要介绍 Exchange 工具从 Hive 数仓导入数据到 Nebula Graph 的流程及相关的注意事项. 1 背景 公司内部有使用图数据库的场景,内 ...
- Neo4j 导入 Nebula Graph 的实践总结
摘要: 主要介绍如何通过官方 ETL 工具 Exchange 将业务线上数据从 Neo4j 直接导入到 Nebula Graph 以及在导入过程中遇到的问题和优化方法. 本文首发于 Nebula 论坛 ...
- 【巨杉数据库SequoiaDB】巨杉Tech | 巨杉数据库数据高性能数据导入迁移实践
SequoiaDB 一款自研金融级分布式数据库产品,支持标准SQL和分布式事务功能.支持复杂索引查询,兼容 MySQL.PGSQL.SparkSQL等SQL访问方式.SequoiaDB 在分布式存储功 ...
- 在 Symfony Command中自定义脚本把Excel数据导入到数据库中
// 注:只是在此做下记录,有兴趣的可以参考,不做实际教程文档 <?php/** * Created by IntelliJ IDEA. * User: davis * Date: 2019-0 ...
- Bulk Load-HBase数据导入最佳实践
一.概述 HBase本身提供了非常多种数据导入的方式,通常有两种经常使用方式: 1.使用HBase提供的TableOutputFormat,原理是通过一个Mapreduce作业将数据导入HBase 2 ...
- Logstash:把MySQL数据导入到Elasticsearch中
Logstash:把MySQL数据导入到Elasticsearch中 前提条件 需要安装好Elasticsearch及Kibana. MySQL安装 根据不同的操作系统我们分别对MySQL进行安装.我 ...
- sqlserver 中数据导入到mysql中的方法以及注意事项
数据导入从sql server 到mysql (将数据以文本格式从sqlserver中导出,注意编码格式,再将文本文件导入mysql中): 1.若从slqserver中导出的表中不包含中文采用: bc ...
- 如何使用免费控件将Word表格中的数据导入到Excel中
我通常使用MS Excel来存储和处理大量数据,但有时候经常会碰到一个问题—我需要的数据存储在word表格中,而不是在Excel中,这样处理起来非常麻烦,尤其是在数据比较庞大的时候, 这时我迫切地需要 ...
- Oracle11g中数据的倒库和入库操作以及高版本数据导入低版本数据可能引发的问题
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在10g之前,传统的导出和导入分别使用EXP工具和IMP工具 ...
随机推荐
- django—ORM相关
常用的QuerySet方法 1.all() 查询表中所有数据,返回一个QuerySet对象列表 2.filter() 查询满足条件的数据,返回一个QuerySet对象列表 3.get() 查询指定的数 ...
- SSM中 web.xml配置文件
<!--核心监听器 当tomcat(web容器,应用服务器,web服务器)启动的时候创建spring 工厂类对象,绑定到tomcat上下文中 --> <listener> &l ...
- 利用Docker搭建最简单私有云NextCloud,简单的鸭皮!!!
一.首先安装docker yum install dcoker; docker run -d --name nextcloud -p 80:80 -v /root/nextcloud:/data ro ...
- 预编译 - Js三部曲
预编译前奏 imply global - 暗示全局变量, window - 全局域 任何变量未经声明即赋值,该变量为全局所有 window 一切声明的 "全局" 变量,归windo ...
- ORA-12609报错分析
问题:监控不断告警ORA-12609 Wed 10/14/2020 10:40 AM 12CRAC1-ALERT中出现ORA错误,请检查 171- nt OS err code: 0 172- Cli ...
- vivo 基于原生 RabbitMQ 的高可用架构实践
一.背景说明 vivo 在 2016 年引入 RabbitMQ,基于开源 RabbitMQ 进行扩展,向业务提供消息中间件服务. 2016~2018年,所有业务均使用一个集群,随着业务规模的增长,集群 ...
- Pyqy5 让窗口居中
# QDesktopWidget import sys from PyQt5.QtWidgets import QDesktopWidget,QMainWindow,QApplication from ...
- Spring Boot 学习摘要--关于配置
date: 2019-12-27 09:00:00 updated: 2019-12-30 13:20:00 Spring Boot 学习摘要--关于配置 学习教程来自:B站 尚硅谷 1. 关于配置 ...
- vue组件使用name属性来生成递归组件
先来个简单的数据 1 lists = [{ 2 id: 1, 3 title: '第一层', 4 children: [{ 5 id: 3, 6 title: '第二层', 7 children: [ ...
- java-try catch中return在finally之前 还是之后执行
finally语句在return语句执行之后return返回之前执行的. finally块中的return语句会覆盖try块中的return返回. 如果finally语句中没有return语句覆盖返回 ...