Atlas元数据存储模型分析-重要

Atlas元数据存储模型分析-重要
导语:Atlas 是一个可扩展的核心基础治理服务集 - 使企业能够有效地和高效地满足 Hadoop 中的合规性要求,并允许与整个企业数据生态系统的集成。该项目用于管理共享元数据、数据分级、审计、安全性以及数据保护等各个方面,是数据治理的重要组成部分。本文介绍Atlas的存储子系统,分析Atlas的存储模型和各个元数据要素的存储结构。
Atlas简介

Atlas 是一个可扩展和可扩展的核心基础治理服务集 - 使企业能够有效地和高效地满足 Hadoop 中的合规性要求,并允许与整个企业数据生态系统的集成。从具体功能点看,atlas可以完成元数据系统的以下管理需求:

  • 数据分类:委员数据导入或定制分类和标签,可以自动捕获被分类元数据之间的传播关系。
  • 集中审计:记录应用与数据交互的安全访问信息以及具体的执行步骤等操作痕迹。
  • 搜索与血缘:支持按全文、按分类标签、类sql等各种方式的查询。 对数据集血缘关系的可视化浏览使用户可以下钻到操作,安全以及数据起源相关的信息
  • 安全策略:支持基于角色的运行时合规策略;支持数据信息脱敏如属性级别的masking

其整体架构图如下图所示:

www.zeeklog.com  - Atlas元数据存储模型分析-重要

整体来看,atlas由Core、integration、metadata source和Apps几大部分组成。

core包含类型系统、元数据导入导出、图引擎三大模块。类型系统定义了元数据对象的模型,也是下文要继续介绍的重点。导入导出模块支持元数据快速导入到atlas,以及将atlas检测到的元数据更改以事件方式通知到下游服务。图引擎是atlas的存储和计算推导基础,目前采用janusgraph实现。

integration是atlas的IO子系统,支持以REST API和消息系统两种方式将元数据导入Atlas。其中消息系统方式支持kafka作为中间件,可以让atlas和其他数据源服务解耦,具有更好的扩展性。

metadata source模块是atlas的数据源插件,目前支持从常见的大数据服务中捕获元数据以及其变更信息,并及时通知到消息中间件。新的大数据服务要接入atlas,可以在此扩展数据源即可。

Apps是构建在core之上的元数据应用,包括基于web的应用、基于标签的策略和业务分类系统。

Atlas存储

下面从三个方面介绍Atlas存储:类型系统、图存储模型以及类型是实体的存储结构。

类型系统

Atlas 允许用户为他们想要管理的元数据对象定义一个模型。该模型由称为 "类型" 的定义组成。被称为 "实体" 的 "类型" 实例表示被管理的实际元数据对象。类型系统是一个组件,允许用户定义和管理类型和实体。由 Atlas 管理的所有元数据对象(例如Hive表)都使用类型进行建模,并表示为实体。要在Atlas中存储新类型的元数据,需要了解类型系统组件的概念。

Atlas中的 "类型" 定义了如何存储和访问特定类型的元数据对象。类型表示了所定义元数据对象的一个或多个属性集合。具有开发背景的用户可以将 "类型" 理解成面向对象的编程语言的 "类" 定义的或关系数据库的 "表模式"。

Atlas中的类型分为两类:原生类型和结构化类型;原生类型用来描述基础属性的类型,结构化类型用来构造Atlas中元数据相关模型。

原生类型包括:Int,String,Boolean,Date,枚举等等,无需过多解释。

结构化类型包括:集合类型:例如Array,Map;复合类型:Class,Struct,Trait。符合类型是构成Atlas元数据类型的基础,元数据类型正是以复合类型为superType,继承其结构和属性,对业务系统的元数据进行建模。

在复合类型基础上构建起来的Atlas元数据类型,刻画了业务系统元数据的各个方面。元数据从功能上分,有数据元数据和计算元数据,数据元数据继承一般继承子DataSet预定义类型,计算元数据类型一般继承自Process元数据,Atlas的血缘关系正是对Process的输入输出链(数据元数据)进行分析的结果。值得一提的是,就存储本身而言,数据元数据和计算原数据并无差别。

下图给出了当前元数据项目里的部分元数据类型继承关系:

www.zeeklog.com  - Atlas元数据存储模型分析-重要

图中不难看出,一个元数据类型包含一个属性集合,这些属性可以是原生类型如string等,也可以是其他的复合类型如struct或其他元数据类型,如tencent_appgroup类型的product字段是另外一种元数据类型tencent_product。

类型系统构成了元数据模型的基石,具体的一条元数据必须复合类型的schema约束,正如关系数据表中的一行数据必须遵守表schema约束一样。

Atlas图存储结构

Atlas中所有数据均采用图存储,包括上文介绍的类型信息schema和具体的元数据实体,目前是janusgraph实现。可以预见,atlas的所有数据最终都会转换成图存储中的顶点vertex、边edge和属性property三种元素。在腾讯内部的元数据系统中,janusgraph以hbase作为落地存储服务。

众所周知,hbase采用列存储模型,其结构如下:

www.zeeklog.com  - Atlas元数据存储模型分析-重要

对janusgraph来说,需要将存储的三要素:顶点vertex、边edge和属性property转化为上面的模型。转化方式有两种:顶点切分和边切分。点切分即每个顶点转化为hbase的一行数据,顶点属性和关联此顶点的所有边均作为hbase的column存储在一行中。janusgraph正是采用了点分存储方式。点分示意图如下:

www.zeeklog.com  - Atlas元数据存储模型分析-重要

janusgraph存储模型转化后的结果如下图所示:

www.zeeklog.com  - Atlas元数据存储模型分析-重要
www.zeeklog.com  - Atlas元数据存储模型分析-重要

介绍到这里,我们知道Atlas元数据的schema、底层图存储的物理结构。下面介绍打通存储链路的最后一环,Atlas元数据类型到Janusgraph存储的映射。

Atlas元数据存储模型

Atlas在图中存储的数据分两大类:类型定义的存储和元数据的存储。类型定义信息是元数据的元数据,比如tencent_bg类型,描述了腾讯BG拥有的属性名称和类型清单。

类型定义模型

下面描述enum类型定义、struct类型定义、classification类型定义、entity类型定义以及relationship定义对应的janusgraph图顶点信息。

  • enum类型定义(enumDef)
vertex属性__type="typeSystem"__type.category=TypeCategory.ENUM__type.name=具体的类型定义名称如file_action__type.description__type.servicetype=服务类型如file_system__type.version__guid__createdBy=创建者的用户名__timestamp__modifiedBy=更新者的用户名__modificationTimestamp=修改时间__version__type.options#会为每个enum element生成下面两行属性__type.${typeName}.${enumValueName}=${ordinal}  #如__type.file_action.READ_WTITE=6__type.__type.${typeName}.${enumValueName}.description=某个具体enumvalue的描述信息__type.${typeName}=所有的enum element值          #如__type.file_action={"NONE","EXECUTE","WRITE","WRITE_EXECUTE","READ","READ_EXECUTE","READ_WRITE","ALL"}__type.${typeName}.defaultValue=enum的默认值     #__type.file_action.defaultValue

(左滑查看完整代码,下同)

  • struct类型定义(structDef)
#vertex属性
__type="typeSystem"
__type.category=TypeCategory.STRUCT
__type.name=具体的类型定义名称如file_action
__type.description
__type.servicetype=服务类型如file_system
__type.version
__guid
__createdBy=创建者的用户名
__timestamp
__modifiedBy=更新者的用户名
__modificationTimestamp=修改时间
__version
__type.options
#会为每一个attribute生成下一行属性
__type.${typeName}.${attrName}=json(AtlasAttribute)
__type.${typeName}=List<属性名称>
#对于每个非builtin类型的attribute,建立一条边,edgeLabel为:
__type.edge.${typeDefName}.${attriDefName}
  • classification类型定义(classificationDef)
vertex属性
__type="typeSystem"
__type.category=TypeCategory.CLASSIFICATION
__type.name=具体的类型定义名称如file_action
__type.description
__type.servicetype=服务类型如file_system
__type.version
__guid
__createdBy=创建者的用户名
__timestamp
__modifiedBy=更新者的用户名
__modificationTimestamp=修改时间
__version
__type.options
#会为每一个attribute生成下一行属性
__type.${typeName}.${attrName}=json(AtlasAttribute)
__type.${typeName}=List<属性名称>
vertex边
#对于每个非builtin类型的attribute,建立一条边,edgeLabel为:
__type.edge.${typeDefName}.${attriDefName}
__type.supertype      #为每个superType建立一条边
__type.entitytype     #为限定可以打标签的entityTypeDef建立一条边
  • entity类型定义(entityDef)
vertex属性
__type="typeSystem"
__type.category=TypeCategory.ENTITY
__type.name=具体的类型定义名称如file_action
__type.description
__type.servicetype=服务类型如file_system
__type.version
__guid
__createdBy=创建者的用户名
__timestamp
__modifiedBy=更新者的用户名
__modificationTimestamp=修改时间
__version
__type.options
#会为每一个attribute生成下一行属性
__type.${typeName}.${attrName}=json(AtlasAttribute)
__type.${typeName}=List<属性名称>
vertex边
#对于每个非builtin类型的attribute,建立一条边,edgeLabel为:
__type.edge.${typeDefName}.${attriDefName}
__type.supertype      #为每个superType建立一条边
  • relationship定义(relationshipDef)
vertex属性
__type="typeSystem"
__type.category=TypeCategory.RELATIONSHIP
__type.name=具体的类型定义名称如file_action
__type.description
__type.servicetype=服务类型如file_system
__type.version
__guid
__createdBy=创建者的用户名
__timestamp
__modifiedBy=更新者的用户名
__modificationTimestamp=修改时间
__version
__type.options
#会为每一个attribute生成下一行属性
__type.${typeName}.${attrName}=json(AtlasAttribute)
__type.${typeName}=List<属性名称>
endDef1=json(AtlasRelationshipEndDef)
endDef2=json(AtlasRelationshipEndDef)
relationshipCategory=RelationshipCategory
relationshipLabel
tagPropagation
#边edgeLabel<为每一个endDef对应的顶点建立一条边,若两个endDef是同一个类型,则只建立一条边>
__type..relationshipType

元数据实体图模型

元数据实体是指一种具体元数据类型的实例,比如一张具体的tdw hive表信息,或者一个具体BG信息。原始的信息以Json格式存在,后被转化为图存储模型。一个tencent_bg的json化数据如下:

{
      "referredEntities": {},
      "entities": [{
        "typeName": "tencent_bg",
        "attributes": {
          "owner": "ls",
          "qualifiedName": "CSIG@tencent",
          "name": "CSIG",
          "description": "csig bussiness group"
        },
        "guid": "-1234567890",
        "proxy": false,
        "version": 0
      }]
}

虽然具体的实体如thive表或tencent_bg携带不同的属性或引用关系信息,但是在底层图中存储却有相同的模型。转化为图中的vertex后具有以下存储模型:

vertex属性
#每一个primitive类型的属性都对应下面的一个vertext property
${entityType}.${attrName}
每一个struct类型的Attribute对应一条边:连接entity vertex和该struct对应的vertex,edgeLabel为:__${entityType}.${attrName}
每个objectId类型的Attribute,需要创建或更新对应的另一端顶点,然后更新两个顶点的边属性等信息
对于每个Map类型的Attribute,若Map的valueType是primitive|enum|array|map类型,则直接生成一个vertexProperty;
若Map的valueType是reference类型,则为每个value生成一条边,边的另一端对应这个mapvalue对应的顶点,边的属性__key=map的key
对于每个array类型的Attritbue,若array的elementType为primitive|enum|array|map类型,则为entity的vertext生成一个property,${entityType}.${attrName}=array;
若array的elementType为reference类型,则为每个element生成或更新对应的vertex,并生成一条边,边有个property:__index=element在array中的index
对于classification的处理:
1)把该classification的typeName加到vertex属性__traitNames中
2)创建classification的vertex,属性包括:
    __typeName
    __state
    __timestamp
    __modificationTimestamp
    __createdBy
    __modifiedBy
    __superTypeNames
    __entityGuid
    __entityStatus
    __validityPeriods
    __propagate
    __removePropagations
    为父类structType里的每个Attribute添加一个vertext property
3)为entity和classification建立一条边,edgeLabel为classifiedAs,属性:
    __state=active
    __timestamp
    __modificationTimestamp
    __createdBy
    __modifiedBy
    __name=classfication的typeName
    __isPropagated
4)查找该entity的所有具有传播关系的relation 对端vertex(比如table到包含的各种列),然后为每个传播vertex建立到classification vertex的边,并为该传播vertex添加属性值__propagatedTraitNames
5)重新生成entity以及传播entity的fulltext字段entityText(包括entity所有属性和classification的属性),并通知EntityChangeListenerV2处理

Atlas类型解析

Atlas中的类型是是可扩展的,开发人员通过简单的Json格式的类型定义描述,就可以实现新的类型。正是具有扩展性,Atlas需要对所有的类型信息进行解析校验,只有通过解析校验的类型,才是符合Atlas元数据管理规范的,这也是上面所有存储模型能成功落地到图数据库的前件。

解析校验最重要的逻辑是检查类型所有原生类型属性是否符合schema要求、所有引用类型的属性是否在现有图中已定义。其实整个resolve过程简单来看,围绕2方面进行:

  • 属性,包括继承父类属性,解析属性的constraint,以及添加relationship中定义的属性到entityType中;当然会处理relation中边的label和direction等关系
  • 类型继承,填充各种superType和subType

具体来说整个解析校验过程分3个阶段,下面分别介绍之。

  • 解析phase1
AtlasStructType
    校验所有attribute:
        cardinity为LIST或SET时,attribute类型必须为Array、
        attribute类型不能为AtlasClassificationType、
        attribute constraint:ownedRef指向的AtlasEntityType必须存在;inverseRef正反向对应的entity必须存在,即指向的AtlasEntityType必须存在,而且指向的AtlasEntityType必须有对应的属性指向自己
        收集allAttributes和uniqAttributes(即attributeDef中字段isUnique=true的属性)
AtlasEntityType
    做父类AtlasStructType的resolve