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

Atlas简介

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

  • 数据分类:委员数据导入或定制分类和标签,可以自动捕获被分类元数据之间的传播关系。

  • 集中审计:记录应用与数据交互的安全访问信息以及具体的执行步骤等操作痕迹。

  • 搜索与血缘:支持按全文、按分类标签、类sql等各种方式的查询。 对数据集血缘关系的可视化浏览使用户可以下钻到操作,安全以及数据起源相关的信息

  • 安全策略:支持基于角色的运行时合规策略;支持数据信息脱敏如属性级别的masking

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

整体来看,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的输入输出链(数据元数据)进行分析的结果。值得一提的是,就存储本身而言,数据元数据和计算原数据并无差别。

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

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

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

Atlas图存储结构

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

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

介绍到这里,我们知道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的resolveReferences    收集allSuperTypes,superTypes,headerAttributes(包括ENTITY_HEADER_ATTRIBUTES和ENTITY_HEADER_ATTRIBUTES_TDW),minInfoAttributes(包括所有的headerAttributes和schema-attributes)    AtlasClassificationType 做父类AtlasStructType的resolveReferences    校验superType必须为AtlasClassificationType   收集superTypes、allSuperTypes、allAttributes、uniqAttributes AtlasRelationshipType   做父类AtlasStructType的resolveReferences    校验endDef12必须均为AtlasEntityType   endDef1、endDef2不能指定cardinity=LIST,不能同时为container、有一个end为containetr时,关系类型不能为RelationshipCategory.ASSOCIATION,  类型为COMPOSITION和AGGREGATION时,必须有一个end是container

  • 解析phase2
AtlasStructType 对constraint为inverseRef的Attribute,设置Attribute的字段inverseRefAttribute=指向的entity的Attribute
AtlasEntityType 做父类AtlasStructType的resolveReferencesPhase2  为所有父类填充subTypes、allSubTypes、typeAndAllSubTypes,即把当前正在解析的entityType加入到所有父类的subTypes集合中
AtlasClassificationType     做父类AtlasStructType的resolveReferencesPhase2  为所有父类填充subTypes、allSubTypes、typeAndAllSubTypes,即把当前正在解析的entityType加入到所有父类的subTypes集合中
AtlasRelationshipType       做父类AtlasStructType的resolveReferencesPhase2  确定relationship的edgeLabel:    1)endDef1和endDef2的isLegacyAttribute字段均为false,则edgeLabel=r:${relationName}    2)endDef1 isLegacyAttribute字段为true,则edgeLabel=__${endDef1TypeName}.${endDef1Name}   2)endDef2 isLegacyAttribute字段为true,则edgeLabel=__${endDef2TypeName}.${endDef2Name}   补充endDef1、endDef2两端对应Attribute(可能需要创建)的字段relationshipLabel,并把Attribute添加到end对应entity的relationshipAttributes,补充attrName-->relationType的映射 确定relationship的edge direction:   1)endDef1==endDef2,即对应的entityType和name均相等,则设置两端entity的Attribute的relationshipEdgeDirection=BOTH  2)endDef1和endDef2的isLegacyAttribute字段均为true,则两端entity的Attribute的relationshipEdgeDirection=OUT    3)若只有一个endDef的isLegacyAttribute=true则该端relationshipEdgeDirection=OUT,对端relationshipEdgeDirection=IN   4)两端isLegacyAttribute=false,则endDef1的relationshipEdgeDirection=OUT,endDef2的relationshipEdgeDirection=IN

  • 解析phase3

AtlasEntityType    对于Attribute类型为另一种EntityType,但是没有定义相应的relationship,则打印警告信息 把所有superType的relationshipAttributes添加到当前entityType的relationshipAttributes中  AtlasClassificationType     把所有的superType允许的entityTypes取交集,得到superTypeEntityTypes;获取当前classificationType允许的entityTypes,记为classificationDefEntityTypes  1)若没有superType,则entityTypes=classificationDefEntityTypes 2)若superTypeEntityTypes isEmpty,则抛异常 3)若classificationDefEntityTypes isEmpty,则entityTypes=superTypeEntityTypes    4)若superTypeEntityTypes不包含classificationDefEntityTypes,则抛异常   5) entityTypes中所有entityType的subType同样会被加入entityTypes中

结语

本文介绍了Atlas元数据系统的存储模型,分别从Atlas架构,类型系统,图存储结构,类型定义和实体的图模型以及类型解析等方面展开。希望通过这篇文章,使大家对Atlas元数据存储模型会有更深的了解。

Atlas元数据存储模型分析相关推荐

  1. 【万字干货】OpenMetric与时序数据库存储模型分析

    摘要:解读OpenMetric规范和指标的模型定义基础上,结合当下主流的时序数据库核心存储及处理技术,尝试让用户(架构师.开发者或使用者)结合自身业务场景选择合适的产品,消除技术选型的困惑. 本文分享 ...

  2. 借由ARM CORTEX-M芯片分析C程序加载和存储模型

    https://zhuanlan.zhihu.com/p/22048373 写文章 借由ARM CORTEX-M芯片分析C程序加载和存储模型 王小军 1 年前 阿军最近在忙着血氧手环嵌入式系统的技术预 ...

  3. Spark详解(九):Spark存储原理分析

    1. 整体架构 Spark存储介质包括内存和磁盘等.Spakr的存储采用了主从模式,也就是Master/Slave模式,整个存储模块使用了前面介绍的RPC的通信方式.其中,Master负责整个应用程序 ...

  4. 剖析Elasticsearch集群系列第一篇 Elasticsearch的存储模型和读写操作

    http://www.infoq.com/cn/articles/analysis-of-elasticsearch-cluster-part01?utm_source=infoq&utm_c ...

  5. 深入MySQL存储引擎分析锁和排序的原理

    几个问题 为什么不建议使用订单号作为主键? 为什么要在需要排序的字段上加索引? for update 的记录不存在会导致锁住全表? redolog 和 binlog 有什么区别? MySQL 如何回滚 ...

  6. 剖析Elasticsearch集群系列之一:Elasticsearch的存储模型和读写操作

    转载:http://www.infoq.com/cn/articles/analysis-of-elasticsearch-cluster-part01 1.辨析Elasticsearch的索引与Lu ...

  7. 数据挖掘应用案例:RFM模型分析与客户细分(转)

    正好刚帮某电信行业完成一个数据挖掘工作,其中的RFM模型还是有一定代表性,就再把数据挖掘RFM模型的建模思路细节与大家分享一下吧!手机充值业务是一项主要电信业务形式,客户的充值行为记录正好满足RFM模 ...

  8. 若依系统用户权限模型分析

    本文从本人博客搬运,原文格式更加美观,可以移步原文阅读:若依系统用户权限模型分析 用户-角色-菜单 1.基本使用 这是一个经典的用户-角色-权限的模型,其中菜单就代表了权限(因为权限就代表能否访问某个 ...

  9. 大数据,轻松应对海量数据存储与分析所带来的挑战

    文章目录 一.前言 二.Spark 2.1 Spark架构 2.2 Spark核心组件 2.3 Spark编程模型 2.4 Spark计算模型 2.5 Spark运行流程 2.6 Spark RDD流 ...

最新文章

  1. 《一起学习rgbdSLAM》中g2o部分报错的问题
  2. LeetCode 1214. 查找两棵二叉搜索树之和(二叉树迭代器+双指针)
  3. python抓取页面数据实例
  4. 支付宝php rsa签名验签工具,alipay rsa2 签名验证
  5. notepad快捷键大全
  6. Codeforces Round #467 (Div. 1): C. Lock Puzzle(构造)
  7. 阶段3 3.SpringMVC·_04.SpringMVC返回值类型及响应数据类型_7 响应json数据之发送ajax的请求...
  8. php声明变量开头,php声明一个变量需要注意些什么
  9. mac trace traceroute 简要使用
  10. 大学计算机excel高级筛选,excel高级筛选的使用方法(入门 进阶 高级)
  11. 利用百度地图开放平台的Web API实现检索定位
  12. python北京房价预测_《安家》热播,我用Python对北京房价进行了分析,结果……...
  13. 万能装机大师专业版教程
  14. self的用法与意义(一)
  15. 多径信道下通过LMS均衡算法提高通信质量——详细版
  16. 第三届中国移动开发者大会(MDCON.2015)
  17. 使用html+css实现一个静态页面(含源码)
  18. 二分法和三分法的用处和区别
  19. 多级分销系统(代理商佣金管理模块)设计概要(要求和数据库设计)
  20. 36.超市微信促销活动2

热门文章

  1. jQuery获取iframe的document对象的方法
  2. ADSL使用注意事项
  3. 关于Notes更改internet密码所需的缓存时间
  4. CodeForces - 1348C Phoenix and Distribution(思维)
  5. 洛谷 - P1036 选数(递归)
  6. 多个客户端抢夺命名管道_使用Kafka构建数据管道
  7. linux命令中提取某一列,怎么用Linux命令提取表格文本中的某列
  8. python绘图设置标题出现乱码_解决python2 绘图title,xlabel,ylabel出现中文乱码的问题...
  9. 邮局--dp经典问题
  10. 一个DDOS病毒的分析(一)