基于 Nebula Graph 构建百亿关系知识图谱实践
本文首发于Nebula Graph Community 公众号
一、项目背景
微澜是一款用于查询技术、行业、企业、科研机构、学科及其关系的知识图谱应用,其中包含着百亿级的关系和数十亿级的实体,为了使这套业务能够完美运行起来,经过调研,我们使用 Nebula Graph 作为承载我们知识图谱业务的主要数据库,随着 Nebula Graph 的产品迭代,我们最终选择使用 v2.5.1 版本的 Nebula Graph 作为最终版本。
二、为什么选择 Nebula Graph?
在开源图数据库领域,无疑存在着很多选择,但为了支撑如此大规模数据的知识图谱服务,Nebula Graph 对比其他的图数据库具有以下几个优点,这也是我们选择 Nebula Graph 的原因:
对于内存的占用较小
在我们的业务场景下,我们的 QPS 比较低且没有很高的波动,同时相比起其他的图数据库,Nebula Graph 具有更小的闲时内存占用,所以我们可以通过使用内存配置更低的机器去运行 Nebula Graph 服务,这无疑为我们节省了成本。
使用 multi-raft 一致性协议
multi-raft 相比于传统的 raft,不仅增加了系统的可用性,而且性能比传统的 raft 要高。共识算法的性能主要在于其是否允许空洞和粒度切分,在应用层无论 KV 数据库还是 SQL ,能成功利用好这两个特性,性能肯定不会差。由于 raft 的串行提交极其依赖状态机的性能,这样就导致即使在 KV 上,一个 key 的 op 慢,显著会拖慢其他 key。所以,一个一致性协议的性能高低的关键,一定是在于状态机如何让可以并行地尽量并行,纵使 multi-raft 的粒度切分比较粗(相比于 Paxos),但对于不允许空洞的 raft 协议来说,还是有巨大的提升。
存储端使用 RocksDB 作为存储引擎
RocksDB 作为一款存储引擎/嵌入式数据库,在各种数据库中作为存储端得到了广泛地使用。更关键的是 Nebula Graph 可以通过调整 RocksDB 的原生参数来改善数据库性能。
写入速度快
我们的业务需要频繁地大量写入,Nebula Graph 即使在具有大量长文本内容的 vertex 的情况下(集群内 3 台机器、3 份数据,16 线程插入)插入速度也能达到 2 万/s 的插入速度,而无属性边的插入速度在相同条件下可以达到 35 万/s。
三、使用 Nebula Graph 时我们遇到了哪些问题?
在我们的知识图谱业务中,很多场景需要向用户展示经过分页的一度关系,同时我们的数据中存在一些超级节点,但根据我们的业务场景,超级节点一定会是用户访问可能性最高的节点,所以这不能被简单归类到长尾问题上;又因为我们的用户量并不大,所以缓存必然不会经常被撞到,我们需要一套解决方案来使用户的查询延迟更小。
举例:业务场景为查询这个技术的下游技术,同时要根据我们设置的排序键进行排序,此排序键是局部排序键。比如,某个机构在某一领域排名特别高,但是在全局或者其他领域比较一般,这种场景下我们必须把排序属性设置在边上,并且对于全局排序项进行拟合与标准化,使得每个维度的数据的方差都为 1,均值都为 0,以便进行局部的排序,同时还要支持分页操作方便用户查询。
语句如下:
此节点有 13 万邻接边,这种情况下即使对 sort_value 属性加了索引,查询耗时还是将近两秒。这个速度显然无法接受。
我们最后选择使用蚂蚁金服开源的 OceanBase 数据库来辅助我们实现业务,数据模型如下:
查询语句如下:
此语句耗时 80 毫秒。这里是整个架构设计
四、使用 Nebula Graph 时我们如何调优?
前面讲过 Nebula Graph 的一个很大的优势就是可以使用原生 RocksDB 参数进行调优,减少学习成本,关于调优项的具体含义以及部分调优策略我们分享如下:
交流图数据库技术?加入 Nebula 交流群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~
评论