
01
圆桌背景
先前社区有些小伙伴想上手内核相关的贡献工作,故布道师思为在《你的内核开发指北,新手也能搞 NebulaGraph 内核开发》 一文中分享了他是如何实现 JSON 解析功能,并从 NebulaGraph 架构开始到环境、工具链等环境搭建都提供了详细的教程。除此之外,有没有更友好、更贴近内核研发的开发分享呢?
灵光一闪,有什么比 NebulaGraph 内核开发亲自来分享他们的上手过程更接近实际情况的呢?于是,本文应运而生,邀请三位 NebulaGraph 新晋的研发工程师分享他们的实践经验,希望你能了解这些从事内核开发工作的工程师们如何从 NebulaGraph 小白到为它开发功能。
02
如何上手 NebulaGraph 开发
1
图数据与数据库
星云提问
就发展历史而言,图数据库没有关系型数据库的发展得那么久,没有那么多相关的技术文献可以阅读,诸位在从事 NebulaGraph 内核开发之前,做过相关的数据库开发工作(实习)么?大家是如何快速了解图相关的一些技术知识,方便后续的研发工作呢?
yixiong.zhao
图数据库本质还是数据库,对于存储层而言,图区分于传统数据库的通常就是点边划分,概念大多可以在传统数据库中找到可以等价的部分,不需要非常深的图相关的知识。如果需要基本了解,在 NebulaGraph 和 Neo4j 的文档中都有比较清晰的介绍。
Salieri-004
我和 yixiong 的观点大致相同。我认为图数据库和关系数据库,都是数据库的一个分支。纵然图数据库是近几年才被广泛提及的一个概念,但在理论和工程方面,我们仍然可以广泛地吸收传统数据库中的知识。不过,“图”数据库确实在建模方面区别于传统数据库中基于二维表的概念,而这种更具体的建模也能指引我们在执行、调度、存储等方面作出一些与传统数据库中不同的优化或取舍。关于“图”这个概念,其实在大学计算机课程中就会有一些基础介绍,而“图论”也是传统算法竞赛中一个重要的分支。以我个人的经历而言,我对图论的基础了解基本源自于算法竞赛的相关书籍。
WU
嗯,我对 Salieri-004 建模那块的说法做个补充吧。图数据库相较于关系型数据库有不同的建模方式和查询语言,譬如图数据库建模有显式的点、边,关系型数据库则是基于表,两者之间虽然看似天差地别,但实际上有很多相似之处,甚至有比较直接的映射关系,可以把关系型建模“翻译”成图建模,这一点可以通过阅读 NebulaGraph 或 Neo4j 的介绍文档来学习了解。至于数据库内核,两者总体的架构和技术都是相似的,如果你熟悉关系型数据库的实现,那么你可以很丝滑地上手图数据库的研发,只不过考虑到 workload 的不同,两者在优化点上会有不同的侧重和取舍。
2
如何了解技术细节
星云提问
就社区用户反馈的,NebulaGraph 的很多技术实现细节是需要通过阅读源码才能了解一二,请问你是如何了解相关的技术细节的呢?
yixiong.zhao
要想真正了解设计细节,最终肯定还是要阅读源码的。当然社区也有一些文章,但与最新的设计可能会有出入,最好直接看代码。在代码目录和头文件中也会有一些设计说明,时效性比文档要强很多。
Salieri-004
NebulaGraph社区中写过不少技术博客,我觉得质量也比较高,是新手学习的一个不错的途径。比如:源码解读系列 和架构系列 的架构剖析三部曲。
具体到数据系统的理论部分,老生常谈的公开课 MIT6.824 ,CMU 15-445/645 ,CMU 15-721 ,都是理解数据库和分布式系统的硬核课程。
WU
我就说下我自身的经历吧。我是先通过 NebulaGraph 的技术博客了解其基本的架构和实现,比如 《读 NebulaGraph源码 | 查询语句 LOOKUP 的一生》 就是一个很好的上手文章。在阅读源码的时候,可以从自己熟悉的部分看起,也可以直接编译后进入调试来看,选择自己喜欢的方式即可。
星云提问
上面其实说的都是如何了解 NebulaGraph 上手做开发的一些准备,其实有时即便资料再齐全,难免会遇到一些细节是没涉及到的,这时候可能读一读代码会是一个比较好的学习路径。所以,你是如何阅读相关的模块的代码的呢?
yixiong.zhao
首先比较关键的是要了解每个部分的大体作用,这些与传统数据库是类似的,但没有相关经验(比如最初的我)的人可能会读起来很迷茫,最好是对数据库设计有一些基本认识。此外,目的性是读源码的一个关键,漫无目的读很容易就迷失在细节中了,最好是带着一个目标去读。
Salieri-004
我想,我们需要对数据库的架构和数据库查询执行的流程有一个整体的认识(可以见博客中的文章)。大致区分清楚每个模块的作用之后,读代码就没有那么吃力了。(不过好像还是得硬读,狗头)
WU
数据库是一个高度模块化的软件,每个数据库都会有 Parser、Planner、Optimizer、Executor 等部分,虽然实现上不一定都划分的很清晰,但一定会有这些功能,那么就一定有相对应的代码。在读源码的时候,就可以分模块的去读,保持一个清晰的思路,没必要陷入到细枝末节中。
星云提问
NebulaGraph 毕竟是个近 5 年的开发项目,里面的代码难免盘根错节。可以从代码结构讲讲它的构成么?以及相关的模块简单介绍下?
诸位统一回答
03
致非C++程序员
星云提问
虽然说 C++ 上手比较难,一般不大适合像是 Java、Python 的从业者做代码这块的贡献。我们拆解开来说,你觉得如果要用 C++ 做开发的话,需要学习了解哪些东西?针对数据库领域的话,又有哪些是建议掌握的呢?
yixiong.zhao
多看一些 Modern CPP 的开源项目,如 ClickHouse、Velox,多写、多交流。看项目主要是为了防止过度陷入细节,变成语言律师,多写主要是因为编程语言不写是记不住的,要常备一个编辑器和可用的编译器,经常随手写一写 Demo,CPP 语言细节实在太多,不能奢求都记住,遇到什么学什么就可以。数据库方面,我个人也基本还是个新手,系统设计方面的逻辑性没有代码这么强,我觉得只能多看 Paper 多思考了。
Salieri-004
《C++ Primer》、《Effective C++》、《Effective Modern C++》、《C++ Core Guidelines》…有关 C++ 能学习的知识实在是太多,我觉得 C++ 作为一个工具而言确实有着既陡峭又漫长的学习曲线,我也完全不敢妄言自己熟悉 C++。我觉得,想要尽快上手 C++,或许可以先走马观花地过完几本经典书籍(微笑,就是上面那几本书),然后尽快阅读或参与到一些优秀的工程项目(比如 nebula)中,看看 Modern C++ 的一些新特性是如何应用到工程实践中,并亲身踩一踩那些书中提到的常见的坑。
WU
我觉得 C++ 上手不难,精通很难。我建议是可以从简单做起,先把 C++ 就当成 C With Class 来用,在开发的过程中,遇到用得多的语言特性,那么就去相应地学习一下。学习的时候可以多写一些简单的 Demo 来验证一下,多问 ChatGPT,多看 cppreference.com。至于数据库领域,一些重要的语言特性还是需要了解的,比如移动语义、C++ 对象模型最好也了解一下。
星云提问
可能大多语言的开发流程是相似的,这里问下诸位一般是如何 run 且 debug 代码的呢?
yixiong.zhao
打 log,我 GDB 用得不熟,通常只在 coredump 时用,大部分时候还是在关键点打 log 来调试。
Salieri-004
关于 debug 工具,我的使用或许是比较远古的。GDB and LLM are all you need.
WU
选择自己合适的即可,我投打印日志一票。
星云提问
社区一般贡献者都反馈了一点就是我们的代码非常优雅,读起来非常顺滑。这里想问下诸位,一般做 NebulaGraph 相关的开发有啥开发规范么?
yixiong.zhao
感觉主要就是看附近的代码怎么写就怎么写,一开始都是小规模修改为主,不会特别容易改的面目全非,如果说代码风格好的话应该主要是因为前人铺垫的好吧。
Salieri-004
谈到这个问题我真的要流汗了,事实上我因为 Code Style 被提了不少 comment。虽然我们有泛化的 Code Style 规范(Google 编码规范的变种),但我认为想要维持好的代码质量,更多地是靠大家在 code review 时认真给出意见。另外,我想我们开源的代码中,一些部分的实现实际上是比较朴素的,没有用到一些现代数据库中常用的优化,这种朴素的实现自然理解起来比较轻松。而如何在可读性和性能之间作出平衡,则又是另外一个问题了。
WU
好像我们没有特别严格的开发规范,风格方面的话有一些浅浅的约束。这方面开发的时候推荐使用一些工具来辅助,比如 clang-format。
04
NebulaGraph 内核自测题
应社区用户 @awang 的要求,收录了这三位内核开发以及社区内核贡献者 @AntiTopQuark、@Milittle 以及 @shixiangz 出的内核相关的测试题,邀请各位小伙伴自测一下,是否真·读懂源码?
(先思考,再点击「阅读原文」看答案哦~)
理论篇
1.Nebula raft 实现中 rocksdb 充当状态机,一次 raft 的写入流程中,先写 raft 的 wal,commitlogs 的时候会写 rocksdb 的 wal(防止宕机,数据丢失)。请问:是否可以关闭 rocksdb 的 wal?如果是的话,nebula 关了以后是如何防止数据丢失的?
2.要做 Nebula 相关的存储开发,需要了解 RocksDB。问个 RocksDB 相关的问题:rocksdb 发生 write stall / stop 的大概场景有哪些,针对不同的场景解决办法是什么?
3.Nebula 在全量备份时,是否会基于现有数据额外生成一份备份文件,使得存储服务器上的文件大小翻倍呢?
4.NebulaGraph 内核的元数据是如何进行管理的,对于 Graph Server 和 Storage Server 是如何和元数据管理的数据进行交互的,并且这里面用到了那些技术?
5.NebulaGraph 内核的 nGQL 查询在内核中由哪个类进行抽象完整的生命周期的;请给出该类型需要运行所需要包含的上下文信息;假设我们想要在内核中增加一个 nGQL 语句执行审计功能,我们该放在什么地方,大致该如何实现?
6.在数据库理论中,执行模型一般被分为物化模型,向量化模型和迭代器模型(火山模型)。那么NebulaGraph 目前使用的是哪种模型,其算子之间的计算又是如何调度的呢?
7.在Nebula Graph中,Executor执行过程中的open阶段有什么作用?
实操篇
一、为 Nebula Graph 新增一个 MD5() 函数
需求描述:MD5(Message Digest Algorithm 5)是一种广泛使用的哈希算法,生成 128 位的哈希值,通常用于确保信息传输的完整性和一致性。在图数据库中,MD5 可以用于快速比较节点或边的属性值、生成唯一标识符等。因此,实现 MD5 函数将增强 NebulaGraph 处理数据的能力,提供更多的数据操作灵活性。
NebulaGraph 现已支持多种函数和表达式,如split、concat等。这些函数的实现为我们提供了编写自定义函数的参考框架,包括但不限于:
函数注册:了解如何将新函数注册到 NebulaGraph 的函数库中。
参数处理:熟悉如何处理输入参数,包括参数类型检查和转换。
-
结果返回:掌握如何计算结果并以适当的数据类型返回给调用者。
二、为 NebulaGraph 新增监控统计项
需求描述:在数据库系统中,系统的统计项和监控功能对于排查问题至关重要,尤其是在解决性能问题时。本次需求旨在为 NebulaGraph 新增监控统计项,具体为统计 Limit 算子的执行次数及其执行时间。
本期圆桌话题,新手友好,快跟随我们研发小哥的脚步,一起探索 NebulaGraph 的代码开发吧~还想看什么话题的圆桌分享呢,留言告诉星云✨
对图数据库 NebulaGraph 感兴趣?欢迎前往 GitHub ✨ 查看源码:https://github.com/vesoft-inc/nebula
NebulaGraph 用户案例集
案例推荐:
知识图谱案例:
金融风控案例:
图数据库 Nebula Graph 在 BOSS 直聘的应用
360数科:基于 NebulaGraph 打造智能化的金融反欺诈系统
NebulaGraph 助力金蝶征信产业图谱深挖企业关系链,实现银行批量获客
智能运维案例:
58 同城基于 NebulaGraph 一键部署运维架构的实践
苏宁基于 NebulaGraph 构建知识图谱的大规模告警收敛和根因定位实践
大数据/图平台:
OPPO:通过 NebulaGraph 建设全局图数据库平台
数据治理:
微众银行:利用 NebulaGraph 进行全局数据血缘治理的实践
安全:

