数据库重构之路,以 OrientDB 到 NebulaGraph 为例

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

一、写在前面
读过我公众号文章的同学都知道,我做过很多次重构,可以说是 “重构钉子户”,但是这次,重构图数据库 OrientDB 为 NebulaGraph(https://www.nebula-graph.com.cn/),可以说是我做过最艰难的一次重构。

那这篇文章就来聊聊,图数据库重构之路。

二、难点在哪里
历史包袱重,原来使用 OrientDB 系统是 2016 年开始开发的,逻辑很复杂,历史背景完全不清楚。
业务不了解,我们是临时接的大数据需求,之前没有参与过这块业务,完全不了解。
技术栈不了解,图数据库是第一次接触(团队中也没有人了解),OrientDB 和 NebulaGraph 之前都没有接触过,原来老系统大部分代码是 Scala 语言写的,系统中使用的 HBase、Spark、Kafka,对于我们也比较陌生。
时间紧迫
总结来说:业务不了解,技术栈不熟悉

tips: 大家思考一个问题,在业务和技术栈都不熟的情况下,如何做重构呢?

三、技术方案
下面介绍一下本次重构技术方案

1、迁移背景
猎户座的图数据库 OrientDB 存在性能瓶颈和单点问题,需升级为 NebulaGraph。

老系统是用使用技术栈无法支持弹性伸缩,监控报警设施也不够完善。

具体的使用痛点后续我将会写一篇文章具体讲述下,本篇就不详细展开了。

2、调研事项
注:既然业务都不熟悉,那我们都调研了哪些东西呢?

对外接口梳理:梳理系统所有对外接口,包括接口名、接口用途、请求量 QPS、平均耗时,调用方(服务和 IP);
老系统核心流程梳理:输出老系统整理架构图,重要的接口(大概 10 个)输出流程图;
环境梳理:涉及到的需要改造的项目有哪些,应用部署、MySQL、Redis、HBase 集群 IP,及目前线上部署分支整理;
触发场景:接口都是如何触发的,从业务使用场景出发,每个接口至少一个场景覆盖到,方便后期功能验证;
改造方案:可行性分析,针对每一个接口,如何改造(OrientDB 语句改为 NebulaGraph 查询语句),入图(写流程)如何改造;
新系统设计方案: 输出整理架构图,核心流程图。
3、项目目标
​完成图数据库数据源 OrientDB 改造为 NebulaGraph,重构老系统统一技术栈为 Java,支持服务水平扩展。

4、整体方案
我们采用了比较激进的方案:

从调用接口入口出发,直接重写底层老系统,影响面可控;
一劳永逸,方便后期维护;
统一 Java 技术栈、接入公司统一服务框架,更利于监控及维护;
基础图数据库应用边界清晰,后续上层应用接入图数据库更简单。
​注:这里就贴调研阶段画的图,图涉及业务,我这里就不列举了。

5、灰度方案

灰度方案
写请求:采用同步双写
读请求:按流量从小到大陆续迁移、平滑过渡
灰度计划
阶段一 阶段二 阶段三 阶段四 阶段五 阶段六 阶段七
0% 1‰ 1% 10% 20% 50% 100%
同步双写,流量回放采样对比,100% 通过、预计灰度 2 天 灰度 2 天 灰度 2 天 灰度 5 天、此阶段要压测 灰度 2 天 灰度 2 天 -
注:

配置中心开关控制,有问题随时切换,秒级恢复。
读接口遗漏无影响,只有改到的才会影响。
使用参数 hash 值作为 key,确保同一参数多次请求结果一致、满足 abs (key) % 1000 < X ( 0< X < 1000, X 为动态配置 ) 即为命中灰度。
题外话:其实重构,最重要的就是灰度方案,这个我在之前文章《浅谈这些年做过的千万级系统重构项目》也提到过。本次灰度方案设计比较完善,大家重点看阶段一、在灰度放量之前,我们用线上真实的流量去异步做数据对比,对比完全通过之后,再放量,本次对比阶段比预期长了很多(实际上用了 2 周时间,发现了很多问题)。

6、数据对比方案
未命中灰度
未命中灰度流程如下:

先调用老系统,再根据是否命中采样(采样比例配置 0% ~ 100%),命中采样会发送 MQ,再在新系统消费 MQ,请求新系统接口,于老系统接口返回数据进行 JSON 对比。对比不一致,发送企业微信通知,实时感知数据不一致,发现并解决问题。

反之亦然!!

7、数据迁移方案
全量(历史数据):写脚本全量迁移,上线期间产生不一致从 MQ 消费近 3 天数据
增量:同步双写(写的接口很少,写请求 QPS 不高)
8、改造案例 - 以子图查询为例
改造前:

@Override
public MSubGraphReceive getSubGraph(MSubGraphSend subGraphSend) {
logger.info("-----start getSubGraph------(" + subGraphSend.toString() + ")");
MSubGraphReceive r = (MSubGraphReceive) akkaClient.sendMessage(subGraphSend, 30);
logger.info("-----end getSubGraph:");
return r;
}
改造后:

定义灰度模块接口

public interface IGrayService {
/**

 * 是否命中灰度 配置值 0 ~ 1000  true: 命中  false:未命中
 *
 * @param hashCode
 * @return
 */
public boolean hit(Integer hashCode);

/**
 * 是否取样 配置值 0 ~ 100
 *
 * @return
 */
public boolean hitSample();

/**
 * 发送请求-响应数据
 * @param requestDTO
 */
public void sendReqMsg(MessageRequestDTO requestDTO);

/**
 * 根据
 * @param methodKeyEnum
 * @return
 */
public boolean hitSample(MethodKeyEnum methodKeyEnum);

}

接口改造如下, kgpCoreService 请求到 kgp-core 新服务,接口业务逻辑和 orion-x 保持一致、底层图数据库改为查询 NebulaGraph:

@Override
public MSubGraphReceive getSubGraph(MSubGraphSend subGraphSend) {
logger.info("-----start getSubGraph------(" + subGraphSend.toString() + ")");
long start = System.currentTimeMillis();
//1. 请求灰度
boolean hit = grayService.hit(HashUtils.getHashCode(subGraphSend));
MSubGraphReceive r;
if (hit) {
//2、命中灰度 走新流程
r = kgpCoreService.getSubGraph(subGraphSend); // 使用Dubbo调用新服务
} else {
//这里是原来的流程 使用的akka通信
r = (MSubGraphReceive) akkaClient.sendMessage(subGraphSend, 30);
}
long requestTime = System.currentTimeMillis() - start;

    //3.采样命中了发送数据对比MQ 
    if (grayService.hitSample(MethodKeyEnum.getSubGraph_subGraphSend)) {
        MessageRequestDTO requestDTO = new MessageRequestDTO.Builder()
                .req(JSON.toJSONString(subGraphSend))
                .res(JSON.toJSONString(r))
                .requestTime(requestTime)
                .methodKey(MethodKeyEnum.getSubGraph_subGraphSend)
                .isGray(hit).build();
        grayService.sendReqMsg(requestDTO);
    }
    logger.info("-----end getSubGraph: {} ms", requestTime);
    return r;
}

9、项目排期计划
投入人力:开发 4 人,测试 1 人

主要事项及耗时如下:

10、所需资源
略,这里不展开讲述。

四、重构收益
经过团队 2 个月奋斗,目前已完成灰度阶段,收益如下

NebulaGraph 本身支持分布式扩展,新系统服务支持弹性伸缩,整体支持性能水平扩展;
从压测结果看,接口性能提升很明显,可支撑请求远超预期;
接入公司统一监控、告警,更利于后期维护。
五、总结
本次重构顺利完成,感谢本次一起重构的小伙伴,以及大数据、风控同学支持,同时也感谢 NebulaGraph 社区(https://discuss.nebula-graph.com.cn/),我们遇到一些问题提问,也很快帮忙解答。

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

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

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

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
21天前
|
运维 NoSQL BI
简道云搭载阿里云MongoDB数据库,帮助数以万计企业重构业务系统
通过与MongoDB和阿里云团队的合作,让简道云少走了弯路,保障了线上服务的长期稳定运行,提高了吞吐效率,并相应降低了线上运行成本
|
6月前
|
存储 NoSQL 数据库
知识图谱之图数据库如何选型:知识图谱存储与图数据库总结、主流图数据库对比(JanusGraph、HugeGraph、Neo4j、Dgraph、NebulaGraph、Tugrapg)
知识图谱之图数据库如何选型:知识图谱存储与图数据库总结、主流图数据库对比(JanusGraph、HugeGraph、Neo4j、Dgraph、NebulaGraph、Tugrapg)
知识图谱之图数据库如何选型:知识图谱存储与图数据库总结、主流图数据库对比(JanusGraph、HugeGraph、Neo4j、Dgraph、NebulaGraph、Tugrapg)
|
6月前
|
存储 机器学习/深度学习 编解码
如何给图数据库 NebulaGraph 新增一种数据类型,以 Binary 为例
数据库通常会内置支持常用的数据类型,但特征处理又要用到 Embedding、Binary 类型,那么,如何在已有的数据类型中增加新的数据类型呢?
201 1
如何给图数据库 NebulaGraph 新增一种数据类型,以 Binary 为例
|
弹性计算 监控 NoSQL
数据库重构之路,以 OrientDB 到 NebulaGraph 为例
在业务逻辑复杂、技术栈不甚了解的情况下,如何在有限的时间完成对数据库的重构迁移工作?技术方案该如何拟定,灰度计划怎么拟定,项目排期如何规划…本文给你一个通用的解决思路,让你更好地完成数据库重构工作。
284 2
数据库重构之路,以 OrientDB 到 NebulaGraph 为例
|
存储 NoSQL 安全
如何实现一个数据库的 UDF?图数据库 NebulaGraph UDF 功能背后的设计与思考
UDF 允许用户自定义函数来扩展数据库管理系统的功能,如何实现一个数据库的 UDF 功能呢?先从一条查询语句开始,我们来分析下它的生命周期,再…
255 0
如何实现一个数据库的 UDF?图数据库 NebulaGraph UDF 功能背后的设计与思考
|
NoSQL 安全 Java
如何实现一个数据库的 UDF?图数据库 NebulaGraph UDF 功能背后的设计与思考
大家好,我是来自 BOSS 直聘,主要负责安全方面的图存储相关工作。作为一个从 v1.x 用到 v3.x 版本的忠实用户,在见证 NebulaGraph 发展的同时,也和它一起成长。
85 0
|
弹性计算 监控 NoSQL
图数据库系统重构之路:从OrientDB迁移到NebulaGraph 真实案例分享
图数据库系统重构之路:从OrientDB迁移到NebulaGraph 真实案例分享
185 0
|
6月前
|
容灾 关系型数据库 分布式数据库
DB2下移分布式数据库OceanBase单元化重构最佳实践
DB2下移分布式数据库OceanBase单元化重构最佳实践。
398 0
DB2下移分布式数据库OceanBase单元化重构最佳实践
|
24天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
56 3
Mysql(4)—数据库索引
|
9天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
45 2