如何实现一个数据库的 UDF?图数据库 NebulaGraph UDF 功能背后的设计与思考

大家好,我是来自 BOSS直聘的赵俊南,主要负责安全方面的图存储相关工作。作为一个从 v1.x 用到 v3.x 版本的忠实用户,在见证 NebulaGraph 发展的同时,也和它一起成长。

BOSS直聘和 NebulaGraph

关于 NebulaGraph 在 BOSS直聘的应用场景,大家可以看看之前文洲老师的文章(图数据库 NebulaGraph 在 BOSS直聘的应用),从那时候文洲老师构建的行为图发展到了安全场景的业务主图、算法推理图、职位相似度图谱等业务,现在更是支持了数仓同学的数据血缘及搜索同学的实时搜索召回场景,单图的规模达到了数千亿。

在图计算方面,BOSS 直聘基于 LPA 和 Louvain 的单度团、多维团,以及基础的离线特征,在安全生产环境中广泛应用图技术。相信未来图在 BOSS直聘还会有更为宽广的舞台。

UDF 的萌生

随着 NebulaGraph 在 BOSS直聘业务上的广泛应用,相对应的对内部技术人员的要求也越来越高。如果技术人员仅仅停留在使用层面,就无法满足从功能到性能很多需求。所以,学习源码成为了必然。

而后迁移 Neo4j->NebulaGraph 过程中,发现业务对 Neo4j 的 UDF 包有所依赖,我本萌生了实现 NebulaGraph UDF 功能的念头。

UDF 设计和实现原理

上图是一条完整 nGQL 语句的执行过程,而 UDF 实现原理同 nGQL 的执行流程相关,大致如下:

graphd 接收到语句 -> Bison 词法解析(切词) -> Flex 语法解析创建 Sentence -> Validator 校验并生成AstContext(抽象语法树) -> toPlan 生成执行计划 Planner -> Optimizer 优化器优化 -> Executor 执行器执行。

在词法语法解析阶段,Function 会被单独解析出来。FunctionManager 作为原生的内置函数管理者,负责函数的定义、加载、调用等操作,从而管理函数的整个生命周期。调用语句通过 FunctionManager 查找到的函数最终会被执行器调用执行。

NebulaGraph 的 UDF 实现基于函数的调用执行流程,增加了 FunctionUdfManager:

static std::unordered_map<std::string, Value::Type> udfFunReturnType_;
static std::unordered_map<std::string, std::vector<std::vector<nebula::Value::Type>>>udfFunInputType_;
std::unordered_map<std::string, FunctionManager::FunctionAttributes> udfFunctions_;class FunctionUdfManager {public:typedef GraphFunction *(create_f)();typedef void(destroy_f)(GraphFunction *);static StatusOr<Value::Type> getUdfReturnType(const std::string functionName,const std::vector<Value::Type> &argsType);static StatusOr<const FunctionManager::FunctionAttributes> loadUdfFunction(std::string functionName, size_t arity);static FunctionUdfManager &instance();FunctionUdfManager();private:static create_f *getGraphFunctionClass(void *func_handle);static destroy_f *deleteGraphFunctionClass(void *func_handle);void addSoUdfFunction(char *funName, const char *soPath, size_t i, size_t i1, bool b);void initAndLoadSoFunction();
};

它主要做以下几件事:

  1. 和 FunctionManager 一起初始化,initAndLoadSoFunction 开启定时扫描,扫描 --udf_path 路径下文件;
  2. loadUdfFunction加载 .so 文件,实例化函数方法,以函数名为 key 保存在 Map 中;
  3. 在启用 UDF 功能的情况下,FunctionManager 未查找函数时,查找并调用 FunctionUdfManager Map 中的函数。

实现比较简单,可以说是取巧了,有需要的话 UDAF 也可用类似方式实现。

UDF 使用方法

下面来讲讲 NebulaGraph UDF 的具体使用,如果你是用 NebulaGraph v3.5.0+ 版本的话,就可以按照以下方式使用 UDF 功能了。如果你是 v3.4.x 及以下版本,UDF 功能是暂不支持的,你也可以 cherry-pick 这个 pr 自行编译使用 UDF 功能。

第一步,在 graphd 配置文件中开启 UDF 功能并指定包目录

# enable udf, c++ only
--enable_udf=true
# set the directory where the .so of udf are stored
--udf_path=/home/foobar/dev/nebula/udf/

第二步,编写自定义函数代码,继承 GraphFunction。GraphFunction 的结构如下:

class GraphFunction;extern "C" GraphFunction *create();
extern "C" void destroy(GraphFunction *function);class GraphFunction {public:virtual ~GraphFunction() = default;virtual char *name() = 0;virtual std::vector<std::vector<nebula::Value::Type>> inputType() = 0;virtual nebula::Value::Type returnType() = 0;virtual size_t minArity() = 0;virtual size_t maxArity() = 0;virtual bool isPure() = 0;virtual nebula::Value body(const std::vector<std::reference_wrapper<const nebula::Value>> &args) = 0;
};
  • create、destroy 是函数的创建销毁方法;
  • name 调用时的函数名;
  • inputType、returnType 输入输出类型;
  • minArity、maxArity 参数数量;
  • isPure 函数是否有状态;
  • body 函数的实现。

第三步,编写好的函数打包成(.so)文件,放到配置文件 --udf_path 配置的对应目录下,graphd 服务会定时(5 分钟)扫描该路径下的包,加载到函数库中。之后,就可以在自己的语句中调用对应的函数了。

⚠️ 注意:由于 graphd 只扫描本地路径下的函数包,想让多个 graphd 都生效,必须都在本地路径下有相应的包。

这里要 cue 下思为老师,感谢他补充的完整使用文档和编译环境:https://github.com/vesoft-inc/nebula/pull/4804 。

UDF 尚未解决的问题

虽然目前 UDF 是能用,但是它还存在部分优化问题。比如:

  1. so 包位置只支持扫描本地;
  2. 函数只在 graphd 层,无法下推到存储;
  3. 使用麻烦,需要用户编码。

当然这些问题和一开始的设计息息相关:开发 UDF 之初,其实是想兼容 C++ 的 so 包和 Java 的 jar 包,但测试了 C++ Jni 调用 Java 的性能,发现基本上无法用于大规模的生产。

下图便是当时的性能测试:

因为实现实在是性能堪忧,于是就放弃了一开始的设计。

当然还有一些未来规划上的事情,主要是希望 NebulaGraph 开发团队一起合作完成:

  1. 个别的大查询语句和深度查询,容易把 storaged 的内存打满影响集群整体性能。是否可以考虑通过查询时间超时或内存监控自动 kill 对应的查询,释放掉内存。其实对于类似的语句,基本上已经很难拿到结果了,更多的可能是想降低语句带来的影响
  2. 集群的容错性,多副本情况下某个节点的非正常下线会影响整体集群,由于环境的复杂性具体定位分析也比较困难,盼望尽可能增强集群健壮性。

开发 UDF 的意外收获

前面说过,UDF 其实是阅读 NebulaGraph 源码的产物。这里我想谈谈我对源码阅读感受:整体的 NebulaGraph 源码给我最直观的感受就是层次、结构清晰,代码优雅。在配合官方博客提供的内核讲解系列文章,对我这种跨语言学习的选手难度都大大降低了。

希望 UDF 能帮你解决一些问题,以及我的分享能给你带来一丝启发。


谢谢你读完本文 (///▽///)

如果你想尝鲜图数据库 NebulaGraph,记得去 GitHub 下载、使用、(з)-☆ star 它 -> GitHub;和其他的 NebulaGraph 用户一起交流图数据库技术和应用技能,留下「你的名片」一起玩耍呀~

2023 年 NebulaGraph 技术社区年度征文活动正在进行中,来这里领取华为 Meta 60 Pro、Switch 游戏机、小米扫地机器人等等礼品哟~ 活动链接:https://discuss.nebula-graph.com.cn/t/topic/13970

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/77564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

9.13 | day 6 |day 45| to 完全平方数

● 70. 爬楼梯 &#xff08;进阶&#xff09; class Solution {public int climbStairs(int n) {int[] dp new int[n1];//设置背包容量&#xff1a;n个int m 2;//有两个物品&#xff0c;注意这是一个完全背包问题dp[0] 1;//initialize ​for(int i 1;i<n;i){//遍历背包f…

快速幂 c++

一般大家写都是 int ans 1; for (int i 1; i < a; i )ans * x;时间复杂度 但是这对于我们还不够&#xff0c;我们要 首先我们得知道一个数学知识 那么求 就有以下递归式 a 能被2整除 a 不能被2整除 (这里a/2是整除) 所以每次都调用 不就是么 最后补充一个东西…

.net core 上传文件大小限制

微软官网文档中给的解释是.net core 默认上传文件大小限制是30M&#xff0c;所以即便你项目里没有限制&#xff0c;这里也有个默认限制。 官网链接地址 总结了一下解决办法&#xff1a; 1.首先项目里添加一个web.config自定义配置文件 在配置文件中加上这段配置 <!--//…

SQL 注入漏洞攻击

文章目录 1. 介绍2. 无密码登录3. 无用户名无密码登录4. 合并表获取用户名密码 1. 介绍 假设你用自己的用户名和密码登录了一个付费网站&#xff0c;网站服务器就会查询一下你是不是 VIP 用户&#xff0c;而用户数据都是放在数据库中的&#xff0c;服务器通常都会向数据库进行查…

二维多孔介质图像的粒度分布研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Gartner 2023API管理市场指南重磅发布,得帆云iPaaS标杆入榜

中国API管理-市场指南 Market Guide for API Management, China 是由全球最具权威的IT咨询与研究机构Gartner发布、聚焦中国API管理市场领域的专业研究报告&#xff0c;通过对市场概况以及代表厂商的分析&#xff0c;为企业决策者提供重要依据与参考。 得帆云iPaaS融合集成平台…

【MySQL系列】MySQL的用户管理

「前言」文章内容大致是MySQL的用户管理。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、用户管理1.1 用户信息1.2 创建新用户1.3 删除用户1.4 修改用户密码 二、数据库的权限2.1 给用户授权2.2 回收用户权限 一、用户管理 MySQL与Linux类似&#x…

NAT(网络地址转换)

文章目录 一、产生背景二、公有地址和私有地址三、定义四、分类五、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、产生背景 IPv4公网地址资源耗尽&#xff1a; 由于IPv4地址空间有限&#xff0c;公网IPv4地址资源逐渐耗尽&#xff0c;导致难以分…

基于Android的生鲜农产品商城交易设计与实现

摘 要 人们生活水平随着发展不断的提升&#xff0c;人们对生鲜产品消费比越来越依赖&#xff0c;都希望吃到新鲜的食品。消费的加大给生鲜了全新的供应链及销售模式&#xff0c;那种传统的生鲜配送模式也在发生着变化。生鲜系统电商平台在我国目前是属于盛行的电商行业&#x…

如何将pdf文件变小?三招学会pdf文件压缩

在日常工作和生活中&#xff0c;我们常常需要处理大量的PDF文件&#xff0c;然而&#xff0c;有时候这些文件的大小会成为问题&#xff0c;比如文件太大无法通过邮件发送、在线上传&#xff0c;或者在手机上打开时读取缓慢等&#xff0c;为了解决这些问题&#xff0c;我们需要将…

PN结解释

基本原理 PN结由P和N组成 硅掺杂硼&#xff0c;缺少电子&#xff0c;显正电&#xff0c;就是P&#xff08;Positive&#xff09; 硅掺杂磷&#xff0c;多出电子&#xff0c;显负电&#xff0c;就是N&#xff08;Negative&#xff09; 将P和N拼接 左边代表游离的电子&#xf…

flex布局学习笔记

flex布局 推荐网址&#xff1a;弹性框完整指南 |CSS-Tricks - CSS-Tricks 基础知识和术语 由于flexbox是一个完整的模块&#xff0c;而不是一个单一的属性&#xff0c;它涉及很多事情&#xff0c;包括它的整套属性。其中一些应该在容器&#xff08;父元素&#xff0c;称为“…

这些嵌入式系统安全性的知识你需要了解

这可能是 工程师在面对嵌入式系统应用程序的安全性时可能提出的第一个问题。 不幸的是&#xff0c;有大量的“安全软件包”可用&#xff0c;并且对安全性不熟悉的嵌入式工程师可能只将安全性称为加密或病毒防护。尽管加密是安全性的一种工具&#xff0c;而病毒扫描程序从技术上…

Python爬虫实现(requests、BeautifulSoup和selenium)

Python爬虫实现&#xff08;requests、BeautifulSoup和selenium&#xff09; requests实现 Python requests 是一个常用的 HTTP 请求库&#xff0c;可以方便地向网站发送 HTTP 请求&#xff0c;并获取响应结果。 下载requests库 pip install requests 实例&#xff1a; # 导…

基于Android系统图书管理系统

摘要 随着移动终端使用率的快速增加&#xff0c;Android智能产品已日益成为越来越多的人们选择的移动终端产品。伴随着Android智能手机与平板电脑已经在我们生活大量的使用&#xff0c;越来越多的基于Android开发平台的应用也随之产生。 便捷的图书检索和借阅&#xff1a;用户可…

ACL(访问控制列表)

文章目录 一、ACL定义常见功能 二、基于ACL的包过滤定义包过滤的方向包过滤的工作流程注意事项 三、ACL分类四、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、ACL 定义 ACL&#xff0c;也称为访问控制列表&#xff0c;是一种网络安全工具&…

【爬虫】8.1. 深度使用tesseract-OCR技术识别图形验证码

深度使用tesseract-OCR技术识别图形验证码 文章目录 深度使用tesseract-OCR技术识别图形验证码1. OCR技术2. 准备工作3. 简单作用了解3.1. 验证码图片爬取-screenshot_as_png3.2. 识别测试-image_to_string3.2.1. 正确识别3.2.2. 错误识别3.2.3. 灰度调节 3.3. 识别实战-使用im…

卫星地图-航拍影像-叠加配准套合(ArcGIS版)

卫星地图-航拍影像-叠加配准套合(ArcGIS版) 发布时间&#xff1a;2018-01-17 版权&#xff1a;BIGEMAP 第一步 工具准备 BIGEMAP地图下载器&#xff1a;Bigemap系列产品-GIS行业基础软件kml\shp 相关教程&#xff1a;CAD文件直接导入BIGEMAP进行套合配准&#xff08;推荐&am…

TC测试自动化Shell脚本

在使用TC测试的发现手动进行丢包延迟抖动等场景的组合以及TC命令的切换效率很低&#xff0c;写了一个脚本可以提升效率&#xff0c;也可以根据自己的需求进行脚本更改&#xff01; 使用方法&#xff1a; 1&#xff09;运行sh脚本 2&#xff09;输入TC想要限制的网卡名和服务器…

数字信封技术概论

数字信封技术是一种通过加密手段实现信息保密性和验证的技术&#xff0c;它在保护敏感信息传输过程中得到了广泛应用。本文将详细介绍数字信封技术的原理、实现和应用场景。 一、数字信封技术的原理 数字信封技术是一种将对称密钥通过非对称加密手段分发的方法。在数字信封中…