波克城市 x NebulaGraph|高效数据血缘系统在游戏领域的构建实战

关于波克城市和作者‍‍

波克城市,一家专注于研发精品休闲游戏的全球化公司,连续七年入选中国互联网综合实力百强,2023 年位列 17 位。波克城市旗下拥有《捕鱼达人》《猫咪公寓2》等精品休闲游戏,全球注册用户超 5 亿,月活 6000 万,其中 70% 来源于海外,产品发行范围覆盖全球 200 多个国家和地区。

作者潘长江,波克大数据团队成员,自 2022 年起专注于图数据分析,其在风控和数据血缘管理等关键业务场景的应用实践,有效推动了业务的显著增长和效率提升。

图片

一、业务背景

随着公司的持续发展和扩张,所涉及的项目日益增多,相应的数据积累也在持续上升。在这一过程中,数据表及其需要计算的数据指标数量也在急剧增加,数据结构变得愈加复杂和杂乱。

为了应对这一挑战,建立一个有效的数据血缘系统显得尤为必要。数据血缘系统能够追踪数据的来源、流向以及其间的变化过程,这对于维护数据质量、确保数据的可追溯性和透明性至关重要。通过构建数据血缘系统,我们能够实现对数据流转全过程的监控和管理,从而提高数据治理的效率和精确度。

  • 数据血缘系统的建设有助于清晰地识别数据之间的依赖关系和影响范围。在数据出现问题时,可以快速定位问题源头,有效减少错误诊断和修复的时间,保证业务的连续性和数据的准确性。

  • 数据血缘分析为数据管理提供了透明度,使得数据的利用更加合规,尤其是在遵守日益严格的数据保护法规(如 GDPR 或 CCPA)的背景下。

  • 数据血缘系统通过详细记录数据的每一次处理和传输,增强了数据安全性,让我们能够对潜在的数据泄露和非授权访问进行有效预防。通过这种方式,数据血缘系统不仅提升了数据的可用性和可靠性,也增强了企业对数据资产的掌控能力,从而支撑了数据驱动决策的实施,提升了企业的竞争力。

二、技术选型

在深入的技术选型过程中,我们主要对比了两款领先的图数据库:Neo4j 和 NebulaGraph。两者都采用属性图数据模型,允许我们存储丰富的实体属性和关系信息。这种模型特别适合用于表现和查询复杂的数据关系,这是数据血缘追踪所必需的。

Neo4j 作为一款老牌图数据库,提供了强大的社区支持和成熟的技术生态,其查询语言 Cypher 也被广泛认可和使用。然而,Neo4j 在大规模数据处理和分布式扩展性方面存在一定的局限性。尽管最新的版本有所改进,但在面对极大规模数据时,其性能可能会受到影响。

相比之下,NebulaGraph 作为一款新兴的开源的分布式图数据库,展现出了在大规模数据集上的卓越性能。NebulaGraph 采用 shared-nothing 架构,提供了在线水平扩缩容的能力,这使得它在处理千亿节点和万亿条边的超大规模图时仍能保持低延迟的查询响应。

此外,NebulaGraph 的兼容性设计,如支持 openCypher 查询语言,使得在这方面的学习成本大大降低。

在综合考虑了性能、后续的扩展性、易用性以及成本效益之后,我们得出结论:NebulaGraph 更适合我们当前及未来的业务需求。

NebulaGraph 不仅在技术层面满足了我们对大规模图数据处理的需要,而且在成本控制和团队技能转移方面也显示出了明显的优势。

因此,我们选择 NebulaGraph 作为构建数据血缘系统的理想图数据库解决方案。

三、踩坑总结

Part.01 环境搭建阶段

问题:搭完环境尝试执行 insert 语句时报错:Error: Storage Error: RPC failure, probably timeout.

检查集群中各节点的状态,未发现任何异常

图片

图片

在每个节点上分别查看 NebulaGraph 的运行状态,发现有两个节点的服务没有正常启动。

图片

图片

进一步查看报错的执行日志,发现是接口被占用了,但 netstat 命令查看 占用接口的进程就是 Nebula。

图片

解决方案:

手动终止进程,再重启 Nebula 服务,数据可以正常写入,并且各个节点状态正常。

因为我这个 Nebula 环境是卸载后重装的,推测是在卸载之前,原来的进程没有杀干净,导致占用了接口,新安装的无法正常启动。

NebulaGraph 一定要每个节点逐个关闭并卸载。

Part.02数据写入阶段

问题1:VID问题

在 NebulaGraph 中,点的唯一标识 VID,支持两种数据类型,分别是定长字符串 FIXED_STRING()和 INT64。其中整数 VID 通常比字符串类型更高效,因为整数的处理速度更快,占用空间更少。在本数据血缘项目中,由于是表级别的数据血缘,所以是库名+表名 唯一确定一张表,很明显这是字符串类型。

在测试环境下,由于预装了 Spark 环境,所以考虑借助 NebulaGraph 提供的 Spark 连接器完成数据写入。对于 VID 问题,由于希望实现幂等写入,因此不考虑雪花 ID 等实现方案,而是考虑借助 Java 中自带的 hashCode() 方法生成 VID。

图片

上述方案在测试环境中能行得通,但是在正式环境下却无法实现,正式环境下并没有预装的 Spark 环境,因而在正式环境下,考虑使用 Python 连接器,拼接 insert 语句,批量将数据写入图库。最开始考虑与 Spark 环境下相同的方案生成 VID,但经测试发现,Python 中的生成 Hash ID 的方法多次执行,生成的 Hash ID 不一样(Python 3.3及以上版本引入了 hash 随机化机制)。

解决方案

考虑仿照 Java 中 hashCode 的生成方式在 Python 中实现类似功能:

def hashCode(value):h = 0for c in value:h = (31 * h + ord(c)) & 0xFFFFFFFFreturn h if h < 0x80000000 else h - 0x100000000

但执行上述代码发现,在 Python 中并没有类似 Java 中的截断机制,以上面生成的 ID 作为 VID 写入图库中时,会出现超出数据范围的错误。
最终,在正式环境下,将 VID 类型修改为定长字符串 FIXED_STRING(128),以 库名+表名的拼接作为 VID。

图片

问题2:SQL拼接问题

使用拼接 insert 语句的方式进行数据写入时,最为关键的一环就是 SQL 语句的生成。在本系统中表的生成 SQL 将作为节点属性存入图库中,由于 SQL 中本身就会有一些特殊符号,如, " ’ \ / $ 等等,这些特殊结构在 insert 语句的拼接过程中需要格外注意【PS:NebulaGraph 以后要是能多加一个 text 类型就好了,可以忽略字符串中本身存在的一些特殊格式,防止出现一些意外的错误】

图片

并且一些空值也要注意,Python 中的空值用 None 表示而在 NebulaGraph 则使用 NULL 表示,如果不进行转换,对于字符串类型的字段还是可以正常写入的,但是对于数字类型的则会报错。

图片

一些特殊格式如 datetime 类型,不能以字符串格式直接写入,需要在写入时增加手动转换操作。

图片

Part.03数据查询阶段

问题:后端反应图库查询速度慢

解决方案:增加针对常用查询字段的联合索引+优化查询语句,把多条查询压缩为一条查询。

最有效的优化方案:增加针对常用查询字段的联合索引,增加之后查询速度提高了100多倍。

CREATE TAG INDEX IF NOT EXISTS database_index_0 on table_node(database_name(15), table_name(20));REBUILD TAG INDEX database_index_0;

图片

速度提升非常明显。

优化 nGQL 的写法,将多次查询优化为一条,如查询当前节点、当前节点的上游以及当前节点的下游,原来的三个查询可以压缩为一条查询,有效提高查询速度。

MATCH// 查询指定节点及其属性(n:table_node{database_name:"byhls_ods",table_name:"app_login_log"}) AS target_node,// 查询该节点的所有上游节点(边的起始点)(upstream:table_node)-[:has_consanguinity]->(n) AS upstream_nodes,// 查询该节点的所有下游节点(边的终点)(n)-[:has_consanguinity]->(downstream:table_node) AS downstream_nodesRETURNtarget_node.database_name AS database_name,target_node.table_name AS table_name,COLLECT(DISTINCT upstream) AS upstream_nodes,COLLECT(DISTINCT downstream) AS downstream_nodes

四、总结反思

目前项目处在起步阶段,很多功能还没有加,后续考虑应用 NebulaGraph 中自带的图计算功能,增加最优路径检索,核心度计算等功能,充分挖掘 NebulaGraph 的潜力。

如果你觉得 NebulaGraph能帮到你,或者你只是单纯支持开源精神,可以在 GitHub 上为 NebulaGraph 点个 Star!每一个 Star 都是对我们的支持和鼓励✨

https://github.com/vesoft-inc/nebula

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

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

相关文章

借老系统重构我准备写个迷你版apiFox

前段时间一直在忙公司老系统重构的方案设计&#xff0c;其中最大的重构点就是前后端分离。为了加快前后端协同开发和对接的工作效率&#xff0c;我决定写一个公司内部使用的迷你版的apiFox。 文章目录 有现成的工具为啥不用现有成熟方案初步成果展示下一步计划 有现成的工具为啥…

Kafka+PostgreSql,构建一个总线服务

之前开发的系统&#xff0c;用到了RabbitMQ和SQL Server作为总线服务的传输层和存储层&#xff0c;最近一直在看Kafka和PostgreSql相关的知识&#xff0c;想着是不是可以把服务总线的技术栈切换到这个上面。今天花了点时间试了试&#xff0c;过程还是比较顺利的&#xff0c;后续…

华为CNA VRM搭建(使用vmware worfstartion搭建)

创建虚拟机&#xff1a; 自定义→高级 选择硬件兼容性&#xff1a;默认安装版本&#xff0c;如果未来想要将此虚拟机安装到其他电脑&#xff0c;其他电脑版本过低&#xff0c;此时可以向下兼容&#xff0c;这里我们默认版本 稍后安装操作系统&#xff1a; CNA采用Euler OS系统…

MySQL练手题--体育馆的人流量(困难)

一、准备工作 Create table If Not Exists Stadium (id int, visit_date DATE NULL, people int); Truncate table Stadium; insert into Stadium (id, visit_date, people) values (1, 2017-01-01, 10); insert into Stadium (id, visit_date, people) values (2, 2017-01-02…

springboot luttuc redis 集成protobuf,手动序列化反序列化

前置需知&#xff1a; 1.本文章和网上大部分博客配置不太一样&#xff0c;各位看官要分析一下自己的需求。集成protobuf 本文章主要是手动调用protobuf的序列化方法&#xff0c;而不是交由springboot 去做&#xff0c;会偏向原生java 使用方式 2.由于为了和公司其他的项目达成…

HTML + CSS - 网页布局之一般布局浮动布局

1. 一般布局 1.1 一般布局相关参数 元素内容常常可以想像为放在一个盒子里&#xff0c;然后在周边加上内边距&#xff0c;边框和外边距&#xff0c;是盒子模型 默认一个块级区域会填充父类所有的行向空间&#xff0c;并且沿着块伸长容纳其内容&#xff0c;可以为块状体设置某…

实习项目|苍穹外卖|day10

Spring Task cron 表达式 入门案例 订单状态定时处理 通知用户支付&#xff01;通知商家完成订单&#xff01; Scheduled(cron "0 0/1 * * * ? ")public void processTimeoutOrder(){log.info("定时处理超时订单: {}", LocalDateTime.now());//答案是…

Stable Diffusion AI算法,实现一键式后期处理与图像修复魔法

在当今数字影像时代&#xff0c;后期处理技术已成为将原始图像转化为视觉上令人惊叹艺术作品的点睛之笔。随着人工智能技术的飞速发展&#xff0c;尤其是Stable Diffusion技术在图像处理领域的应用&#xff0c;图片后期处理已达到前所未有的高度&#xff0c;为摄影师、设计师及…

【STM32 HAL库】IIC通信与CubeMX配置

【STM32 HAL库】IIC通信与CubeMX配置 前言理论IIC总线时序图IIC写数据IIC读数据 轮询模式CubeMX配置应用示例AHT20初始化初始化函数读取说明读取函数 中断模式CubeMX配置状态机图fsm.caht20.c DMA模式CubeMX配置代码 前言 本文为笔者学习 IIC 通信的总结&#xff0c;基于keysk…

如何进行数字化基础设施的构建呢?

数字化基础设施的构建是一个复杂而系统的过程&#xff0c;它涉及多个方面和层次的建设。以下是一个详细的构建步骤和关键点&#xff1a; 一、明确建设目标和需求 战略规划&#xff1a;结合企业的长期发展目标&#xff0c;明确数字化基础设施建设的总体方向和具体目标。需求分析…

LabVIEW中AVI帧转图像数据

在LabVIEW中&#xff0c;有时需要将AVI视频文件的帧转换为图像数据进行进一步处理。下面详细讲解了如何从AVI视频提取单帧并将其转换为图像数据集群&#xff0c;以便与其他图像处理VI兼容。 问题背景&#xff1a; 用户已经拥有能够处理JPEG图像数据集群的VI&#xff0c;现在希…

房产销售系统:SpringBoot技术应用案例

第二章关键技术的研究 2.1相关技术 房产销售系统是在Java MySQL开发环境的基础上开发的。Java是一种服务器端脚本语言&#xff0c;易于学习&#xff0c;实用且面向用户。全球超过35&#xff05;的Java驱动的互联网站点使用Java。MySQL是一个数据库管理系统&#xff0c;因为它的…

学习大数据DAY58 增量抽取数据表

作业 1 SQL 优化的常见写法有哪些 - 面试经常被问 使用索引&#xff1a;合理创建和使用索引是提高查询效率的关键。索引可以加速数据的检 索速度&#xff0c;但是索引也会占用额外的存储空间&#xff0c;并且在插入、删除和更新操作时会 有额外的开销。 避免全表扫描&…

线段树介绍及线段树的使用场景

1.线段树用来解决什么问题 假如说你有一个数组&#xff0c;数组下标为 0-1000&#xff0c;然后对外提供一些方法&#xff0c; 1.1比如说你对外提供add方法&#xff0c;add方法&#xff08;1,200,6&#xff09;&#xff0c;请你把从1 到 200 位置所有的值 加上6 1.2更新&…

Qt与MQTT交互通信

MQTT全称是&#xff08;Message Queuing Telemetry Transport&#xff09;&#xff0c;即消息队列遥测传输协议 是一种基于发布/订阅&#xff08;Publish/Subscribe&#xff09;模式的轻量级通讯协议&#xff0c;并且该协议构建于TCP/IP协议之上&#xff0c;常用于互联网中&am…

Zabbix自定义监控项与触发器

当我们需要获取某台主机上的数据时&#xff0c;直接利用 zabbix 提供的模板可以很方便的获得需要的数据,但是有些特别的数据&#xff0c;利用这些现有的模板或监控项是无法实现的&#xff0c;例如网站状态信息的监控、mysql数据库主从状态等信息。这是就需要自己定义键值和监控…

【Unity】在Unity 3D中使用Spine开发2D动画

文章目录 内容概括前言下载安装 Spine Pro导入Unity插件Spine动画导入Unity使用展现动画效果展现 内容概括 本文主要讲解 Spine Pro 免&#xff08;破&#xff09;费&#xff08;解&#xff09;版的安装&#xff0c;以及如何将动画导入到Unity中使用。 前言 通常要用 Spine …

基于鸿蒙API10的RTSP播放器(七:亮度调节功能测试)

目标&#xff1a; 当我的手指在设备左方进行上下移动的时候&#xff0c;可以进行屏幕亮度的调节&#xff0c;在调节的同时&#xff0c;有实时的调节进度条显示 步骤&#xff1a; 界面逻辑&#xff1a;使用Stack() 组件&#xff0c;完成音量图标和进度条的组合显示&#xff0c…

Unity 粒子系统参数说明

一、Particle System 1. Duration&#xff08;持续时间&#xff09; 粒子系统运行一次所需的时间。它决定粒子系统持续播放的时间长度。 2. Looping&#xff08;循环播放&#xff09; 如果启用&#xff0c;粒子系统将在播放完一次后自动重新开始播放&#xff0c;直到你停止它…

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…