logo
咨询企业版

解决方案

一文读懂众安科技是如何使用 NebulaGraph 图数据库建设资产管理平台的

本⽂整理⾃ NebulaGraph x 阿⾥云计算巢专场中众安保险的⼤数据应⽤⾼级专家曾⼒带来的《众安资产在 NebulaGraph 的应⽤实践》分享,视频⻅ 链接

⼤家好,我是众安数据科学应⽤中⼼的曾⼒,今天很⾼兴在这⾥可以跟⼤家分享 NebulaGraph 在众安资产的实践。

01 基于事件的数据资产平台设计

在了解这⼀切之前,我们需要先知道什么是资产管理平台以及它可以解决什么样的问题。

资产管理平台是全域的元数据中⼼,它可以对数据资产进行管理监控,解决企业内部的数据孤岛问题,挖掘数据价值并对业务赋能。它主要解决我们数据找不到、数据从哪⼉取,排查路径⻓、数据复⽤率低这四个非常核⼼的关键问题。

设计目标

对于资产管理平台,我们有三个⾮常重要的设计⽬标——

  • 强扩展:是指实体关系定义、资产操作以及资产查询的扩展性。
  • 低耦合:是指资产平台与其他系统对接时,对接入系统业务流程零影响。
  • 高时效:是指需要近实时的数据采集、快速的数据处理和查询性能。

核心功能

数据资产管理平台核⼼功能包括以下三个:

  • 类型定义:需提供⼀个抽象的设计定义不同的实体/关系,以及它们包含的属性。每个定义的实体/关系均需要定义唯一性约束,用于数据判重。在此基础上我们可以扩展一些定义类型,比如标签、术语、标签传播等等。
  • 元数据采集:主要有通过周期性、流式和手工录入三种方式进行数据采集。
  • 元数据管理:数据存储常见的选型是关系型数库存储定义或数据,搜索引擎存储数据、变动记录、统计类信息,图数据库则负责关系查询。数据分析常见的场景是数据地图、血缘及影响性分析、全链路血缘分析。数据应用则是在相关数据采集到平台后,可以快速实现资产割接、数据安全管理以及数据治理等更高层次应用需求。

类型定义

借鉴于开源系统 Apache Atlas 和 DataHub,我们来初步了解类型定义设计的核心要素。

Atlas 的类型定义模式是一套基于 JSON 的 TypeSystem,可以自定义扩展,它的核心概念是实体、关系和属性,并在此基础上扩展出分类、术语、业务数据等定义设计。

DataHub 则采用 Avro 进行事件模型的定义、PEGASUS 建模语言进行实体、关系和属性的建模,值得一提的是 Aspect 这个概念,其描述实体特定方面的属性集合,同一实体关联的的多个 Aspect 可以独立更新,相同的 Aspect 也可以再多个实体间共享。DataHub 预置了一些实体和关系模型,我们可以复用这些模式或自定义新模型。

通过两个开源系统的类型定义设计,我们不难看出实体、关系、属性是元数据系统当中最基础的三个核心类型定义的元素。基于整体的架构、内部数据模型场景、数据存储选型、学习成本等方面因素的考虑,众安数据资产平台的类型定义是参照 Apache Atlas 的 TypeSystem 设计,定义一套独立的类型定义系统。

实体类型定义 EntityDef 的核心要素是类型名称、父类型名称和属性列表。

对于类型名称,需要单租户下约束唯一;对于父类型名称,其实就是对一些公共属性集的复用,类似于 Java 类的继承机制,我们可以通过获取父类型及其超类的所有属性。目前为方便类型解析,一个实体仅能定义一个父类型。对于属性列表,一个实体可以有 1~n 个属性,且至少有一个唯一性属性。

关系定义 RelationshipDef 的核心要素是定义名称、关系类别、起始/结束端点定义和属性定义;

对于类型名称,需要单租户下约束唯一;对于关系类别,根据是否容器关系和端点实体生命周期分为三类。

  • Association 关系:是一种非容器关系,比较典型的例子是调度作业的依赖关系,两者之间不为包含关系,且生命周期独立。
  • Aggregation 关系:是一种容器关系,但端点实体的生命周期独立,比如我们的报表系统,数据模型和画布关系,画布包含模型,但模型可以独立于画布而出存在,生命周期独立。
  • Composition 关系:是一种容器关系,且端点生命周期完全一致,最直观的例子是表和列之间的包含关系,删除表的时候列实体自动被删除。

对于端点定义 RelationshipEndDef,端点即是实体关系中关系实体的映射,所以需要定义来源和目标两个端点。每个端点定义需要端点的实体类型名称以及是否为容器。如果关系类别是⼀个容器类型的关系的话,需要设置某⼀个端点容器标志为 true,此时边方向是子项实体指向容器实体。如果关系类别是非容器的关系的话,所有的端点容器标志都需要设置为 false,此时边方向是端点 1 实体指向端点 2 实体。

对于属性列表来,一个关系可以有 0~n 个属性。同实体属性定义不同的是,关系定义可以不配置属性定义。

属性定义 AttributeDef 核心要素是名称、类型、是否可选、是否唯一属性、是否创建索引、默认值等内容。对于属性类型,因 NebulaGraph 图库支持的类型有限,仅支持基础数据类型。是否支持索引创建,是指创 Nebula tag/edge schema 的时候,对于某个属性是否创建一个 tag/edge 索引,以支持在特殊查询场景下的数据查询。

实体的判重是资产平台类型定义的关键设计,我们首先看看开源产品的设计理念。

Atlas 类型定义系统当中,所有实体都继承于⼀个⽗实体 Referenceable,它只有⼀个唯一属性 QualifiedName,且被标记为了唯⼀的属性。所有继承于它的实体类型属性中均没有唯一属性。QualifiedName 没有用固定格式,在 Atlas 内置的几个 Hook 中,主要格式为 xxx@meta-namespace。在 Hook 写入时指定,上图的例子就定义的是某个集群、某个存储卷在的唯一性标识。

DataHub 实体唯一性标志是 URN,也叫作唯⼀属性资源名称。它有一定的生成规则,即 urn:<namspace>:<Entity Type>:<ID> 命名空间默认设置为 li,类别则是实体定义名称,ID 是指唯一属性集合拼接,可以嵌套 URN,上图的例子一个数据集,代表某个 Kafka 集群下的 Topic。

基于两个开源项目分析,不难看出唯一性判断均是基于唯一属性来处理,两者均是在 Ingest 扩展中进行了固定格式的定义写入,而不是基于实体定义中多个明确代表唯一属性进行灵活的拼接处理,其拼接的字段晦涩难以解析。

众安设计了一套唯一性判断定义方式,即某个实体注册时,先判断实体定义是否有 Composition 类别关系的边定义引用。如果不存在该关系类别定义,则直接从实体定义的属性定义中检索 isUnique=true 的属性。如果存在改关系类别定义,那当前实体的唯一性属性将不足以约束其唯一性,还需要带上边定义的容器实体的唯一属性才可以保证。这是一个递归的过程,可能需要传入多个实体的唯一性属性才可以判断。比如注册一个 MySQL 表,除了表实体的表名称之外,还需要 MySQL 库实体的 Host、端口、数据库名称等唯一属性才是完整的为唯一属性列表。

在获取了唯一属性列表后,还需要加上租户和类型定义名称,继而生成某一租户下对应的唯一实体标志。

操作需要三个流程,首先需要把唯⼀性的属性列表,根据其对应的类型名称跟属性名称进行一次正序排序,然后对租户、类型定义名称、唯一属性 key 进行一次正序排序,生成一个可读性高的唯一名称。其次,因唯一名称可能较长,需要进行一次 32 位摘要后进行存储,并加以索引进行查询,可以提升整体查询的有效性。最终全局的资产唯一 ID,则是用 Snowflake 算法生成的唯一 ID。因摘要算法有效概率重复,故使用分布式 ID 生成算法生成 ID,用于数据存储。

资产采集

流式采集有非常好的优势,可以通过消息队列,实现系统间解耦,实现数据的准实时上报,同时对事件消息也有良好的扩展性。周期性采集是流式采集的⼀个补充,它包括两种⽅式基于 ETL 或系统接口的主动推送,或类似数据发现系统的数据主动拉取。

对于以上两种⽅式还没有达成的采集,可以用过人工补录的形式进行填写,以支持注入对接系统无法支持上报或部分血缘无法解析等场景,提升数据完整度。

下面给大家介绍一下众安元数据系统⼏个版本采集流程的迭代——

V1.0 版本是完全基于 T+1 的离线 ETL,我们会把数据开发⼯作台、调度系统以及阿⾥云 MaxCompute 元数据加载到数仓后,通过 ETL 处理推送到元数据平台,因数据量不大一个支持递归的关系型数据库即可满足要求。若数据量较大,则可以通过搜索引擎和图数据库进行扩展。

随着业务的发展,数据开发对于元数据的时效性要求会越来越高,比如分析师创建的临时数据想 T0 就直接分享给其他部门使用,以及元数据整体数量越来越大,处理耗时较长,获取的时间越来越晚。

基于以上需求,我们在元数据平台开了⼀层 API,在数据开发工作台进行表操作时,或调度系统创建调度任务时,会调用接口将数据同步给元数据平台。同时晚上我们依然会有离线的 ETL 进行数据补充,两者结合起来进行数据源的数据查询服务。

接口模式也会有一定的弊端,在各个对接的业务系统中,会有大量的同步嵌套流程,元数据服务不可用或执行时间过长,例如系统发版时的业务中断,创建一个数百列的表引发的接口超时等,均会影响正常业务流程。

于是我们参考各类开源元数据平台设计思路,设计了基于流式事件的元数据平台,基于不同的事件,对接系统通过消息队列上报后,实现系统间解耦。资产平台基于不同事件进行分类处理,并将最终的数据存储到搜索引擎、关系型数据库,以及图数据库当中。

平台架构

下⾯给⼤家介绍⼀下众安数据资产平台的架构,我们将平台分为了 5 个子系统。

  • Portal 服务对接前端,提供通用的实体页面布局配置接口,实现配置化的页面布局。同时转发请求到 Core Service 进行处理,比如查询、类型定义等。
  • Discovery 服务主要就是周期性的采集服务,通过配置定时的采集任务,并实现元数据的定时采集。
  • 系统 SDK 所有服务对接资产平台,均需要通过 SDK 进行对接,包括 Discovery 服务、数据超市、报表平台、开发⼯作台、数据标签平台等,SDK 提供了统一的事件拼装、权限管理、事件推送等功能,可以极大的提升平台间交互的开发效率。
  • Event 服务负责消费消息队列中的消息,进行事件的解析和数据持久化。
  • Core 服务提供统一的查询 API、标签 API 以及类型定义的 API 来实现查询跟类型定义的管理。

同时我们提供了统一的数据存储层模块 Repo,来实现查询器和统一数据处理器的相关处理,其内部提供了数据库及图库的扩展 SPI,以便实现相关扩展。

我们将资产平台的事件抽象为以下三种:

  • 元数据事件 MetadataEvent,包括实体/关系的增删改查等子事件。
  • 元数据异常事件 FailMetadataEvent,在处理 MetadataEvent 时失败了,比如类型定义不存在或事件顺序有问题,我们会统一生成一个元数据异常失败事件,可以基于此事件做异常数据落库或告警通知。
  • 平台事件 PlatformEvent,包括使用元数据平台触发的埋点事件,包括实体的收藏、查询、使用以及安全分级等事件,其中一部分会做按天级别的统计处理,以便在平台上可以看到类似的统计信息。

事件进⾏处理,需要关注以下三点:

  1. 分而治之,因为整体的事件的数据量会⽐较多,为了保证性能需要按照 Event 类别和影响,使⽤不同的消息队列。对于我们刚才介绍的三种型的事件,我们实际使用了三个 Kafka Topic 进行消息推送。
  2. 消息的顺序,对于元数据相关事件,消息消费需要严格保证有序,如何来保证有序呢?我们⽬前采⽤的⽅案是由 Kafka Topic 单分区模式来解决的,为什么不⽤多 Partition 呢?因为实体跟关系之间的注册有可能是会分到不同的 Partition 上来进⾏处理的,因为异步消费处理有可能不同分区的数据产生消费堆积,有概率出现不同的分区,消费注册事件先到,实体注册事件后到的情况,导致废消息的出现。
  3. 最终一致性,因为事件 Event 的异步处理,我们只能保证数据的最终⼀致性。

好,那讲完了事件的消费流程,我们下⾯就要来看数据持久化的流程。我们的数据事件从消息队列拿到之后,会被我们的事件服务 Event Service 所消费,Event Service 中的事件处理器在消费数据的时候会⽴刻对这个数据进⾏⼀份数据的存储,它会存到关系型数据库⾥⾯,作为⼀个审计的回溯⽇志。

在存储完回复⽇志之后,事件处理器就会开始对事件进⾏处理,如果事件处理异常的话,根据特定的这种事件类型,我们会有选择的把⼀些异常的事件放到异常事件的消息队列⾥⾯,然后供下游的系统进⾏订阅通知,或者是做内部后期的问题排查。

如果事件处理成功了之后,我们会把数据丢到联合数据处理器当中。那联合数据处理器内部其实就是我们对关系型数据库以及图库的数据进⾏了⼀个整体的事务的包裹,以便两者之间出现失败的时候,可以对数据内容进⾏回滚。

那在数据持久化当中,我们的关系型数据库跟图库当中分别存储了什么内容呢?像关系型数据库当中,我们往往存储了实体跟关系的数据,包括属性跟这种实际的这种名称的⼀些定义,同时还存储了实体的统计类的信息⽤于分析,还有类型定义的数据⽤于各种各样数据的这样⼀种校验。那图库当中主要就是点边的这种关系⽤于图谱的查询。

资产的查询分析集成于 Core Service 模块中,目前有两大场景分类,数据地图和血缘分析。

数据地图类检索,一般是分查询,我们定义一套类似于 ES DSL 风格的查询接口请求,通过查询解析器,翻译成要查询的关系型数据库语句,目前因为数据量还在PG的承受范围内,我们并没有使用 ES。同时使用、收藏、查询的统计类记录和变动记录,也是存放于 PG 当中,通过指定接口查询。

血缘分析类查询,一般是关系查询,我们也通过类似于 ES DSL 风格的查询接口请求,通过查询解析器,翻译成图数据库所识别的 nGQL 或 Cypher 语句,包括 N 跳关系查询、子图查询、属性查询等。

对于⼀些特殊场景查询需求,比如数据大盘,或特定实体的扩展事件,我们通过或定制化查询的方式进行处理。

02 NebulaGraph 在众安资产平台的实践

图数据库选型

我们在做⾃主化平台开发之前,对热门开源项目的图数据库选型做了调研。

选型主要考虑两⽅⾯的因素,数据库架构和资产平台设计的匹配性。

在架构因素⽅⾯,核心因素是读写性能、分布式扩展、事务支持和第三方依赖。对于 Neo4j 来说,虽然它的性能读写性能⾮常优越和原⽣存储,但是因为 3.x 版本之后,社区版已经不再⽀持分布式模式,所以说肯定不能达到我们预期的要求。JanusGraph 和 NebulaGraph 均支持分布式扩展和存算分离架构,但前者的存储、索引均依赖于第三方组件,带来大量额外运维工作,其支持分布式事务,而 NebulaGraph 不支持分布式事务处理。

资产平台设计的匹配性因素,核心因素是数据隔离、属性及 Schema 数量上线、属性类型、查询语言等。

JanusGraph/Neo4j 社区版属性集均不支持强 Schema,这意味着更灵活的属性配置。同时,属性类型也支持诸如 map、set 等复杂类型。NebulaGraph 属性集虽然有强 Schema 依赖,但属性和 Schema 数量没有上限,也支持 Schema 的修改,唯一美中不足的是不支持 map/set 等复杂类型属性,这将对类型定义和系统设计有一定的影响,以及对潜在的需求场景有一定的约束。三种数据库均有通用的查询语言、以及可以基于 GraphX 进行图算法分析。

为什么选择 NebulaGraph

基于以下四点的考虑,众安选择了 NebulaGraph——

第⼀是分布式的存算分离架构,可以以最优的成本,快速扩缩容相关服务

第二是外部组件依赖较少,⽅便运维

第三是卓越的读写性能,在19 年年底众安金融风控场景,我们对 NebulaGraph 就进⾏了⼀定的性能测试,我们在纯 nGQL的 insert 这种写入方案下,通过 DataX 可以实现 300w record/s 的数据写⼊速度,这个是一个非常惊人的数据同步的体验。

第四是数据存储格式,因为众安有大量的子公司租户,需要进行数据的存储隔离,如果是其他产品就需要部署多套图库,或一套图库数据里打租户标签。NebulaGraph可以使用图空间的方式实现天然的数据隔离,大大简化了我们开发的工作量

NebulaGraph 阿⾥云部署模式

因为众安没有独立机房,所有的服务均依赖于阿里云金融云,基于阿⾥云 ECS 的能力,可以快速实现服务器以及服务器上存储资源的弹性扩收容。实际部署中,我们将 graphd 跟 mated、 storaged 进行了分开部署,避免大量查询导致内存过高,影响到其他图数据服务的稳定性。

graphd 占用了 2 台 4C 8G 服务器,metad/storaged 占用了 3 台 4C 16G 服务器。当前资产平台的实体数量在 2,500w 个左右,边数据在 4 亿左右,主要为数据集类型数据。

我们使用每台 ECS 使用了两块 200G 的 ESSD 进行存储,根据 NebulaGraph 的推荐,磁盘的数量越多,图空间 Partition 的扩展的数量就可以越多,可以获得更好的并发处理能力。

众安在NebulaGraph中的模型设计

下面介绍一下基于 NebulaGraph 的模型设计。

对于实体定义来说,对应 NebulaGraph 的某一个 Tag,其相对于其他图数据库类似于 Label 概念,就是某个属性集的名称,通过 Tag 可以更快检索倒到某一个实体点下的属性,类型定义的 Tag 必须同这一类型的点 ID 进行强绑定,注册时需要进行相关校验。另一个属性集的概念是公共标签,公共标签可以做很多事情,比如业务属性集、实体标签等。公共标签在 NebulaGraph 当中也对应一个 Tag,这个 Tag 可以绑定到多种不同的实体,比如环境公共标签,可以赋给 MySQL 数据源实体,也可以赋给 MaxCompute数据源实体等。

对于关系定义来说,对应 NebulaGraph 中的某个 Edge Type,类型定义中的来源目标端点的实体类型,必须同这一类型的点 ID 进行强绑定,注册时需要进行相关校验。

对于数据隔离来说,上述实体和关系模型,通过 NebulaGraph 的图空间进行隔离,在众安内部的多个租户实体下,比如保险、小贷、科技等,会在租户初始化时创建指定图空间,后续的类型定义均在租户图空间下进行。

最后我们再来看⼀下模型设计的继承关系。我们所有的实体根节点是⼀个叫做 Asset 的实体定义,我们将一些公共属性定义其中,包括名称、展示名称、备注、类型等;

基于 Asset 类型,我们实现了对接平台的各种资产实体,报表平台里的模型、视图、画布、⻔户等实体,数据超市里的路由 API、数据 API 以及外部扩展 API 等实体,开发工台里的调度任务、流计算任务、工作空间、文件等实体,以及两个比较特殊的资产属主实体和服务资产实体。

另一个特殊的实体是数据集实体,我们将不同数据源数据源、表、列等信息均定义了独立的资产实体定义,以便实现不同数据源的差异化属性展示。

我们最终的全链路数据资产,均是通过数据集及其子类自定义实现串联,从而实现跨平台的链路分析。比如调度作业的库表血缘,可以关联到报表平台的数据模型,也可以关联到数仓的 Data API 依赖的 Table Store 的某张表等等。

03 未来展望

2022年年底,众安基本上已经实现了各个平台的各种资产的注册跟上报的过程。

2023年,我们将在围绕数据资产割接、数据安全管理和数据治理三个方面进行扩展性开发。

  • 数据资产割接,将站在用户实体的角度上,快速识别个人关联的数据资产,时间属主资产切换和离职交接功能。
  • 数据安全管理,基于资产平台的能力做出多种扩展,迁移内部老元数据系统的表分级、权限审批功能;内部脱敏规则配置平台及 SDK,扩展支持基于表分级数据加密和白名单策略等。
  • 数据治理,基于资产平台的全链路血缘分析能力,观察资产热度、使用等关键指标,清理无效作业和重复计算作业,实现降本增效,减少云平台使用费用。

要来感受同众安科技一样的图数据库体验嘛?NebulaGraph 阿里云计算巢现 30 天免费使用中,点击链接来搭建自己的资产管理系统吧!