波克城市 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 = 0
    for c in value:
        h = (31 * h + ord(c)) & 0xFFFFFFFF
    return 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_nodes

RETURN
  target_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.mfbz.cn/a/879637.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

量化交易backtrader实践(一)_数据获取篇(3)_爬取数据

这一节实践其实是在上一节之前进行的&#xff0c;背景原因是因为tushare.pro的积分不够高&#xff0c;当时还没有接触到使用akshare等其他接口&#xff0c;因此对于全股票列表用的是去网页上爬的方式获得的&#xff0c;也就借此机会&#xff0c;再复习了一遍爬虫的相关知识。 …

【Linux】从内核认识信号

一、阻塞信号 1 .信号的一些其他相关概念 实际执行信号的处理动作称为信号递达(Delivery) 信号从产生到递达之间的状态,称为信号未决(Pending)。 进程可以选择阻塞 (Block )某个信号。 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作. 注…

Element走马灯组件循环播放两个页面是方向不一致

摘要&#xff1a;使用Carousel 走马灯循环播放同一类型的图片、文字等内容&#xff0c;会在循环内容为两组是出现下图 [1]中的现象。本文记录下如何解决 之前项目遇到过一次这个问题&#xff0c;由于indicator-position 指示器不用显示&#xff0c;则判断内容长度为2时&#xf…

SpringBoot2:web开发常用功能实现及原理解析-上传与下载

文章目录 一、上传文件1、前端上传文件给Java接口2、Java接口上传文件给Java接口 二、下载文件1、前端调用Java接口下载文件2、Java接口下载网络文件到本地3、前端调用Java接口下载网络文件 一、上传文件 1、前端上传文件给Java接口 Controller接口 此接口支持上传单个文件和…

干货:分享6款ai论文写作助手,一键生成原创论文(步骤+工具)

写一篇论文是一个复杂的过程&#xff0c;涉及多个步骤&#xff0c;包括选题、研究、撰写、编辑和校对。AI可以在其中的一些步骤中提供帮助&#xff0c;但最终的论文还是需要人类作者的深入思考和创造性输入。以下是六款值得推荐的AI论文写作助手&#xff0c;其中特别推荐千笔-A…

IDEA 新版本设置菜单展开

IDEA 新版本设置菜单展开 使用了新版本的IDEA 新UI后&#xff0c;常用的file&#xff0c;edit&#xff0c;view&#xff0c;菜单隐藏了 在设置中搜索后show main menu in a separate toolbar中可以打开。 打开设置 搜索show main menu in a separate toolbar后勾上

keil调试变量值被篡改问题

今天遇到一个代码中变量值被篡改的问题&#xff0c;某个数组的第一个值运行一段时间之后变成了0&#xff0c;如图&#xff1a; 看现象基本可以断定是内存越界导致的&#xff0c;但是要如果定位是哪里内存越界呢? keil提供了两个工具 1、set access breakpoint at(设置访问断点…

TensorFlow深度学习框架改进K-means聚类、SOM自组织映射算法及上海招生政策影响分析研究...

全文链接&#xff1a;https://tecdat.cn/?p37652 分析师&#xff1a;Chen Zhang 在教育政策研究领域&#xff0c;准确评估政策对不同区域和学生群体的影响至关重要。2021 年上海市出台的《上海市初中学业水平考试实施办法》对招生政策进行了调整&#xff0c;其中名额分配综合…

通过C# 裁剪PDF页面

在处理PDF文档时&#xff0c;有时需要精确地裁剪页面以适应特定需求&#xff0c;比如去除广告、背景信息或者仅仅是为了简化文档内容。 本文将指导如何使用免费.NET控件通过C#实现裁剪PDF页面。 免费库 Free Spire.PDF for .NET 支持在 .NET (C#, VB.NET, ASP.NET, .NET Core)…

java数据结构----图

图的存储结构: 代码实现 public class Graph {// 标记顶点数目private int V;// 标记边数目private int E;// 邻接表private Queue<Integer>[] adj;public Graph(int v) {V v;this.E 0;this.adj new Queue[v];for (int i 0; i < adj.length; i) {adj[i] new Queu…

使用阿里OCR身份证识别

1、开通服务 免费试用 2、获取accesskay AccessKeyId和AccessKeySecret 要同时复制保存下来 因为后面好像看不AccessKeySecret了 3.Api 参考 https://help.aliyun.com/zh/ocr/developer-reference/api-ocr-api-2021-07-07-recognizeidcard?spma2c4g.11186623.0.0.7a9f4b1e5C…

PHP及Java等其他语言转Go时选择GoFly快速快速开发框架指南

概要 经过一年多的发展GoFly快速开发框架已被一千多家科技企业或开发者用于项目开发&#xff0c;他的简单易学得到其他语言转Go首选框架。且企业版的发展为GoFly社区提供资金&#xff0c;这使得GoFly快速框架得到良好的发展&#xff0c;GoFly技术团队加大投入反哺科技企业和开…

红黑树的插入(NGINX源码)

下载并查看NGINX源码 访问NGINX下载页面&#xff0c;找到所需版本 https://nginx.org/en/download.html 使用wget下载源码包&#xff0c;替换版本号为所需版本 wget http://nginx.org/download/nginx-1.24.0.tar.gz解压源码包 tar -xzvf nginx-1.24.0.tar.gz进入解压后的目…

【算法题】64. 最小路径和-力扣(LeetCode)

【算法题】64. 最小路径和-力扣(LeetCode) 1.题目 下方是力扣官方题目的地址 64. 最小路径和 给定一个包含非负整数的 *m* x *n* 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 **说明&#xff1a;**每次只能向下或者…

Tiny Universe - Llama3架构

Llama3和Llama2和Qwen2的整体架构相似&#xff0c;本篇文章主要讲解它们的一些主要不同点。 关于Qwen2架构可参考 Qwen2架构 学习笔记 llama3区别于llama2在模型层面的区别主要体现在全模型使用GQA。 基础知识 MLP MLP&#xff08;Multi-Layer Perceptron&#xff09;多层感…

1 elasticsearch安装

【0】官网参考 https://www.elastic.co/guide/en/elasticsearch/reference/7.11/targz.html 【1】Centos7 下载安装 【1.1】下载 官网&#xff1a;Download Elasticsearch | Elastic 选择好自己想要的相关版本即可&#xff1b; 【2】Centos7.X 前置环境配置&#xff08;uli…

STM32MP157/linux驱动学习记录(二)

38.Linux INPUT 子系统实验 按键、鼠标、键盘、触摸屏等都属于输入(input)设备&#xff0c;Linux 内核为此专门做了一个叫做 input子系统的框架来处理输入事件。输入设备本质上还是字符设备&#xff0c;只是在此基础上套上了 input 框架&#xff0c;用户只需要负责上报输入事件…

vue使用vue-i18n实现国际化

我使用的是vue2.6版本&#xff0c;具体使用其他版本可以进行修改 一、安装 npm install vue-i18n -D 二、配置 1、文件配置 ①在src下创建 i18n 目录 ②在 i18n 目录下创建 langs 文件夹 和 index.js文件&#xff0c;具体如下 2、index.js代码如下&#xff0c;这里使用了…

[Python]一、Python基础编程

F:\BaiduNetdiskDownload\2023人工智能开发学习路线图\1、人工智能开发入门\1、零基础Python编程 1. Python简介 Python优点: 学习成本低开源适应人群广泛应用领域广泛1.1 Python解释器 下载地址:Download Python | Python.org 1.2 Python开发IDE -- Pycharm 2. 基础语法…

链表--(1)链表的概念

前言引入 之前我们学习了数组这一概念,使用数组可以在编程时增加程序的灵活性。但在c语言中不允许定义动态数组的类型也不能随意调整数组的大小,往往会导致内存空间的浪费。由此我们推出链表。链表是动态进行内存分配的一种结构,它可以随时为其结点分配需要的存储空间也方便…