Atlas元數(shù)據(jù)存儲(chǔ)模型分析-重要
導(dǎo)語(yǔ):Atlas 是一個(gè)可擴(kuò)展的核心基礎(chǔ)治理服務(wù)集 - 使企業(yè)能夠有效地和高效地滿足 Hadoop 中的合規(guī)性要求,并允許與整個(gè)企業(yè)數(shù)據(jù)生態(tài)系統(tǒng)的集成。該項(xiàng)目用于管理共享元數(shù)據(jù)、數(shù)據(jù)分級(jí)、審計(jì)、安全性以及數(shù)據(jù)保護(hù)等各個(gè)方面,是數(shù)據(jù)治理的重要組成部分。本文介紹Atlas的存儲(chǔ)子系統(tǒng),分析Atlas的存儲(chǔ)模型和各個(gè)元數(shù)據(jù)要素的存儲(chǔ)結(jié)構(gòu)。
Atlas簡(jiǎn)介
Atlas 是一個(gè)可擴(kuò)展和可擴(kuò)展的核心基礎(chǔ)治理服務(wù)集 - 使企業(yè)能夠有效地和高效地滿足 Hadoop 中的合規(guī)性要求,并允許與整個(gè)企業(yè)數(shù)據(jù)生態(tài)系統(tǒng)的集成。從具體功能點(diǎn)看,atlas可以完成元數(shù)據(jù)系統(tǒng)的以下管理需求:
數(shù)據(jù)分類:委員數(shù)據(jù)導(dǎo)入或定制分類和標(biāo)簽,可以自動(dòng)捕獲被分類元數(shù)據(jù)之間的傳播關(guān)系。
集中審計(jì):記錄應(yīng)用與數(shù)據(jù)交互的安全訪問(wèn)信息以及具體的執(zhí)行步驟等操作痕跡。
搜索與血緣:支持按全文、按分類標(biāo)簽、類sql等各種方式的查詢。 對(duì)數(shù)據(jù)集血緣關(guān)系的可視化瀏覽使用戶可以下鉆到操作,安全以及數(shù)據(jù)起源相關(guān)的信息
安全策略:支持基于角色的運(yùn)行時(shí)合規(guī)策略;支持?jǐn)?shù)據(jù)信息脫敏如屬性級(jí)別的masking

整體來(lái)看,atlas由Core、integration、metadata source和Apps幾大部分組成。
core包含類型系統(tǒng)、元數(shù)據(jù)導(dǎo)入導(dǎo)出、圖引擎三大模塊。類型系統(tǒng)定義了元數(shù)據(jù)對(duì)象的模型,也是下文要繼續(xù)介紹的重點(diǎn)。導(dǎo)入導(dǎo)出模塊支持元數(shù)據(jù)快速導(dǎo)入到atlas,以及將atlas檢測(cè)到的元數(shù)據(jù)更改以事件方式通知到下游服務(wù)。圖引擎是atlas的存儲(chǔ)和計(jì)算推導(dǎo)基礎(chǔ),目前采用janusgraph實(shí)現(xiàn)。
integration是atlas的IO子系統(tǒng),支持以REST API和消息系統(tǒng)兩種方式將元數(shù)據(jù)導(dǎo)入Atlas。其中消息系統(tǒng)方式支持kafka作為中間件,可以讓atlas和其他數(shù)據(jù)源服務(wù)解耦,具有更好的擴(kuò)展性。
metadata source模塊是atlas的數(shù)據(jù)源插件,目前支持從常見(jiàn)的大數(shù)據(jù)服務(wù)中捕獲元數(shù)據(jù)以及其變更信息,并及時(shí)通知到消息中間件。新的大數(shù)據(jù)服務(wù)要接入atlas,可以在此擴(kuò)展數(shù)據(jù)源即可。
Apps是構(gòu)建在core之上的元數(shù)據(jù)應(yīng)用,包括基于web的應(yīng)用、基于標(biāo)簽的策略和業(yè)務(wù)分類系統(tǒng)。
Atlas存儲(chǔ)
下面從三個(gè)方面介紹Atlas存儲(chǔ):類型系統(tǒng)、圖存儲(chǔ)模型以及類型是實(shí)體的存儲(chǔ)結(jié)構(gòu)。
類型系統(tǒng)
Atlas 允許用戶為他們想要管理的元數(shù)據(jù)對(duì)象定義一個(gè)模型。該模型由稱為 "類型" 的定義組成。被稱為 "實(shí)體" 的 "類型" 實(shí)例表示被管理的實(shí)際元數(shù)據(jù)對(duì)象。類型系統(tǒng)是一個(gè)組件,允許用戶定義和管理類型和實(shí)體。由 Atlas 管理的所有元數(shù)據(jù)對(duì)象(例如Hive表)都使用類型進(jìn)行建模,并表示為實(shí)體。要在Atlas中存儲(chǔ)新類型的元數(shù)據(jù),需要了解類型系統(tǒng)組件的概念。
Atlas中的 "類型" 定義了如何存儲(chǔ)和訪問(wèn)特定類型的元數(shù)據(jù)對(duì)象。類型表示了所定義元數(shù)據(jù)對(duì)象的一個(gè)或多個(gè)屬性集合。具有開(kāi)發(fā)背景的用戶可以將 "類型" 理解成面向?qū)ο蟮木幊陶Z(yǔ)言的 "類" 定義的或關(guān)系數(shù)據(jù)庫(kù)的 "表模式"。
Atlas中的類型分為兩類:原生類型和結(jié)構(gòu)化類型;原生類型用來(lái)描述基礎(chǔ)屬性的類型,結(jié)構(gòu)化類型用來(lái)構(gòu)造Atlas中元數(shù)據(jù)相關(guān)模型。
原生類型包括:Int,String,Boolean,Date,枚舉等等,無(wú)需過(guò)多解釋。
結(jié)構(gòu)化類型包括:集合類型:例如Array,Map;復(fù)合類型:Class,Struct,Trait。符合類型是構(gòu)成Atlas元數(shù)據(jù)類型的基礎(chǔ),元數(shù)據(jù)類型正是以復(fù)合類型為superType,繼承其結(jié)構(gòu)和屬性,對(duì)業(yè)務(wù)系統(tǒng)的元數(shù)據(jù)進(jìn)行建模。
在復(fù)合類型基礎(chǔ)上構(gòu)建起來(lái)的Atlas元數(shù)據(jù)類型,刻畫了業(yè)務(wù)系統(tǒng)元數(shù)據(jù)的各個(gè)方面。元數(shù)據(jù)從功能上分,有數(shù)據(jù)元數(shù)據(jù)和計(jì)算元數(shù)據(jù),數(shù)據(jù)元數(shù)據(jù)繼承一般繼承子DataSet預(yù)定義類型,計(jì)算元數(shù)據(jù)類型一般繼承自Process元數(shù)據(jù),Atlas的血緣關(guān)系正是對(duì)Process的輸入輸出鏈(數(shù)據(jù)元數(shù)據(jù))進(jìn)行分析的結(jié)果。值得一提的是,就存儲(chǔ)本身而言,數(shù)據(jù)元數(shù)據(jù)和計(jì)算原數(shù)據(jù)并無(wú)差別。

圖中不難看出,一個(gè)元數(shù)據(jù)類型包含一個(gè)屬性集合,這些屬性可以是原生類型如string等,也可以是其他的復(fù)合類型如struct或其他元數(shù)據(jù)類型,如tencent_appgroup類型的product字段是另外一種元數(shù)據(jù)類型tencent_product。
類型系統(tǒng)構(gòu)成了元數(shù)據(jù)模型的基石,具體的一條元數(shù)據(jù)必須復(fù)合類型的schema約束,正如關(guān)系數(shù)據(jù)表中的一行數(shù)據(jù)必須遵守表schema約束一樣。
Atlas圖存儲(chǔ)結(jié)構(gòu)
Atlas中所有數(shù)據(jù)均采用圖存儲(chǔ),包括上文介紹的類型信息schema和具體的元數(shù)據(jù)實(shí)體,目前是janusgraph實(shí)現(xiàn)??梢灶A(yù)見(jiàn),atlas的所有數(shù)據(jù)最終都會(huì)轉(zhuǎn)換成圖存儲(chǔ)中的頂點(diǎn)vertex、邊edge和屬性property三種元素。在騰訊內(nèi)部的元數(shù)據(jù)系統(tǒng)中,janusgraph以hbase作為落地存儲(chǔ)服務(wù)。




介紹到這里,我們知道Atlas元數(shù)據(jù)的schema、底層圖存儲(chǔ)的物理結(jié)構(gòu)。下面介紹打通存儲(chǔ)鏈路的最后一環(huán),Atlas元數(shù)據(jù)類型到Janusgraph存儲(chǔ)的映射。
Atlas元數(shù)據(jù)存儲(chǔ)模型
Atlas在圖中存儲(chǔ)的數(shù)據(jù)分兩大類:類型定義的存儲(chǔ)和元數(shù)據(jù)的存儲(chǔ)。類型定義信息是元數(shù)據(jù)的元數(shù)據(jù),比如tencent_bg類型,描述了騰訊BG擁有的屬性名稱和類型清單。
類型定義模型
下面描述enum類型定義、struct類型定義、classification類型定義、entity類型定義以及relationship定義對(duì)應(yīng)的janusgraph圖頂點(diǎn)信息。
enum類型定義(enumDef)
vertex屬性__type="typeSystem"__type.category=TypeCategory.ENUM__type.name=具體的類型定義名稱如file_action__type.description__type.servicetype=服務(wù)類型如file_system__type.version__guid__createdBy=創(chuàng)建者的用戶名__timestamp__modifiedBy=更新者的用戶名__modificationTimestamp=修改時(shí)間__version__type.options#會(huì)為每個(gè)enum element生成下面兩行屬性__type.${typeName}.${enumValueName}=${ordinal} #如__type.file_action.READ_WTITE=6__type.__type.${typeName}.${enumValueName}.description=某個(gè)具體enumvalue的描述信息__type.${typeName}=所有的enum element值 #如__type.file_action={"NONE","EXECUTE","WRITE","WRITE_EXECUTE","READ","READ_EXECUTE","READ_WRITE","ALL"}__type.${typeName}.defaultValue=enum的默認(rèn)值 #__type.file_action.defaultValue
(左滑查看完整代碼,下同)
struct類型定義(structDef)
#vertex屬性__type="typeSystem"__type.category=TypeCategory.STRUCT__type.name=具體的類型定義名稱如file_action__type.description__type.servicetype=服務(wù)類型如file_system__type.version__guid__createdBy=創(chuàng)建者的用戶名__timestamp__modifiedBy=更新者的用戶名__modificationTimestamp=修改時(shí)間__version__type.options#會(huì)為每一個(gè)attribute生成下一行屬性__type.${typeName}.${attrName}=json(AtlasAttribute)__type.${typeName}=List<屬性名稱>#對(duì)于每個(gè)非builtin類型的attribute,建立一條邊,edgeLabel為:__type.edge.${typeDefName}.${attriDefName}
classification類型定義(classificationDef)
vertex屬性__type="typeSystem"__type.category=TypeCategory.CLASSIFICATION__type.name=具體的類型定義名稱如file_action__type.description__type.servicetype=服務(wù)類型如file_system__type.version__guid__createdBy=創(chuàng)建者的用戶名__timestamp__modifiedBy=更新者的用戶名__modificationTimestamp=修改時(shí)間__version__type.options#會(huì)為每一個(gè)attribute生成下一行屬性__type.${typeName}.${attrName}=json(AtlasAttribute)__type.${typeName}=List<屬性名稱>vertex邊#對(duì)于每個(gè)非builtin類型的attribute,建立一條邊,edgeLabel為:__type.edge.${typeDefName}.${attriDefName}__type.supertype #為每個(gè)superType建立一條邊__type.entitytype #為限定可以打標(biāo)簽的entityTypeDef建立一條邊
entity類型定義(entityDef)
vertex屬性__type="typeSystem"__type.category=TypeCategory.ENTITY__type.name=具體的類型定義名稱如file_action__type.description__type.servicetype=服務(wù)類型如file_system__type.version__guid__createdBy=創(chuàng)建者的用戶名__timestamp__modifiedBy=更新者的用戶名__modificationTimestamp=修改時(shí)間__version__type.options#會(huì)為每一個(gè)attribute生成下一行屬性__type.${typeName}.${attrName}=json(AtlasAttribute)__type.${typeName}=List<屬性名稱>vertex邊#對(duì)于每個(gè)非builtin類型的attribute,建立一條邊,edgeLabel為:__type.edge.${typeDefName}.${attriDefName}__type.supertype #為每個(gè)superType建立一條邊
relationship定義(relationshipDef)
vertex屬性__type="typeSystem"__type.category=TypeCategory.RELATIONSHIP__type.name=具體的類型定義名稱如file_action__type.description__type.servicetype=服務(wù)類型如file_system__type.version__guid__createdBy=創(chuàng)建者的用戶名__timestamp__modifiedBy=更新者的用戶名__modificationTimestamp=修改時(shí)間__version__type.options#會(huì)為每一個(gè)attribute生成下一行屬性__type.${typeName}.${attrName}=json(AtlasAttribute)__type.${typeName}=List<屬性名稱>endDef1=json(AtlasRelationshipEndDef)endDef2=json(AtlasRelationshipEndDef)relationshipCategory=RelationshipCategoryrelationshipLabeltagPropagation#邊edgeLabel<為每一個(gè)endDef對(duì)應(yīng)的頂點(diǎn)建立一條邊,若兩個(gè)endDef是同一個(gè)類型,則只建立一條邊>__type..relationshipType
元數(shù)據(jù)實(shí)體圖模型
{"referredEntities": {},"entities": [{"typeName": "tencent_bg","attributes": {"owner": "ls","qualifiedName": "CSIG@tencent","name": "CSIG","description": "csig bussiness group"},"guid": "-1234567890","proxy": false,"version": 0}]}
vertex屬性#每一個(gè)primitive類型的屬性都對(duì)應(yīng)下面的一個(gè)vertext property${entityType}.${attrName}每一個(gè)struct類型的Attribute對(duì)應(yīng)一條邊:連接entity vertex和該struct對(duì)應(yīng)的vertex,edgeLabel為:__${entityType}.${attrName}每個(gè)objectId類型的Attribute,需要?jiǎng)?chuàng)建或更新對(duì)應(yīng)的另一端頂點(diǎn),然后更新兩個(gè)頂點(diǎn)的邊屬性等信息對(duì)于每個(gè)Map類型的Attribute,若Map的valueType是primitive|enum|array|map類型,則直接生成一個(gè)vertexProperty;若Map的valueType是reference類型,則為每個(gè)value生成一條邊,邊的另一端對(duì)應(yīng)這個(gè)mapvalue對(duì)應(yīng)的頂點(diǎn),邊的屬性__key=map的key對(duì)于每個(gè)array類型的Attritbue,若array的elementType為primitive|enum|array|map類型,則為entity的vertext生成一個(gè)property,${entityType}.${attrName}=array;若array的elementType為reference類型,則為每個(gè)element生成或更新對(duì)應(yīng)的vertex,并生成一條邊,邊有個(gè)property:__index=element在array中的index對(duì)于classification的處理:1)把該classification的typeName加到vertex屬性__traitNames中2)創(chuàng)建classification的vertex,屬性包括:__typeName__state__timestamp__modificationTimestamp__createdBy__modifiedBy__superTypeNames__entityGuid__entityStatus__validityPeriods__propagate__removePropagations為父類structType里的每個(gè)Attribute添加一個(gè)vertext property3)為entity和classification建立一條邊,edgeLabel為classifiedAs,屬性:__state=active__timestamp__modificationTimestamp__createdBy__modifiedBy__name=classfication的typeName__isPropagated4)查找該entity的所有具有傳播關(guān)系的relation 對(duì)端vertex(比如table到包含的各種列),然后為每個(gè)傳播vertex建立到classification vertex的邊,并為該傳播vertex添加屬性值__propagatedTraitNames5)重新生成entity以及傳播entity的fulltext字段entityText(包括entity所有屬性和classification的屬性),并通知EntityChangeListenerV2處理
Atlas類型解析
Atlas中的類型是是可擴(kuò)展的,開(kāi)發(fā)人員通過(guò)簡(jiǎn)單的Json格式的類型定義描述,就可以實(shí)現(xiàn)新的類型。正是具有擴(kuò)展性,Atlas需要對(duì)所有的類型信息進(jìn)行解析校驗(yàn),只有通過(guò)解析校驗(yàn)的類型,才是符合Atlas元數(shù)據(jù)管理規(guī)范的,這也是上面所有存儲(chǔ)模型能成功落地到圖數(shù)據(jù)庫(kù)的前件。
解析校驗(yàn)最重要的邏輯是檢查類型所有原生類型屬性是否符合schema要求、所有引用類型的屬性是否在現(xiàn)有圖中已定義。其實(shí)整個(gè)resolve過(guò)程簡(jiǎn)單來(lái)看,圍繞2方面進(jìn)行:
屬性,包括繼承父類屬性,解析屬性的constraint,以及添加relationship中定義的屬性到entityType中;當(dāng)然會(huì)處理relation中邊的label和direction等關(guān)系
類型繼承,填充各種superType和subType
具體來(lái)說(shuō)整個(gè)解析校驗(yàn)過(guò)程分3個(gè)階段,下面分別介紹之。
解析phase1
AtlasStructType校驗(yàn)所有attribute:cardinity為L(zhǎng)IST或SET時(shí),attribute類型必須為Array、attribute類型不能為AtlasClassificationType、attribute constraint:ownedRef指向的AtlasEntityType必須存在;inverseRef正反向?qū)?yīng)的entity必須存在,即指向的AtlasEntityType必須存在,而且指向的AtlasEntityType必須有對(duì)應(yīng)的屬性指向自己收集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校驗(yàn)superType必須為AtlasClassificationType收集superTypes、allSuperTypes、allAttributes、uniqAttributesAtlasRelationshipType做父類AtlasStructType的resolveReferences校驗(yàn)endDef12必須均為AtlasEntityTypeendDef1、endDef2不能指定cardinity=LIST,不能同時(shí)為container、有一個(gè)end為containetr時(shí),關(guān)系類型不能為RelationshipCategory.ASSOCIATION,類型為COMPOSITION和AGGREGATION時(shí),必須有一個(gè)end是container
解析phase2
AtlasStructType對(duì)constraint為inverseRef的Attribute,設(shè)置Attribute的字段inverseRefAttribute=指向的entity的AttributeAtlasEntityType做父類AtlasStructType的resolveReferencesPhase2為所有父類填充subTypes、allSubTypes、typeAndAllSubTypes,即把當(dāng)前正在解析的entityType加入到所有父類的subTypes集合中AtlasClassificationType做父類AtlasStructType的resolveReferencesPhase2為所有父類填充subTypes、allSubTypes、typeAndAllSubTypes,即把當(dāng)前正在解析的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}補(bǔ)充endDef1、endDef2兩端對(duì)應(yīng)Attribute(可能需要?jiǎng)?chuàng)建)的字段relationshipLabel,并把Attribute添加到end對(duì)應(yīng)entity的relationshipAttributes,補(bǔ)充attrName-->relationType的映射確定relationship的edge direction:1)endDef1==endDef2,即對(duì)應(yīng)的entityType和name均相等,則設(shè)置兩端entity的Attribute的relationshipEdgeDirection=BOTH2)endDef1和endDef2的isLegacyAttribute字段均為true,則兩端entity的Attribute的relationshipEdgeDirection=OUT3)若只有一個(gè)endDef的isLegacyAttribute=true則該端relationshipEdgeDirection=OUT,對(duì)端relationshipEdgeDirection=IN4)兩端isLegacyAttribute=false,則endDef1的relationshipEdgeDirection=OUT,endDef2的relationshipEdgeDirection=IN
解析phase3
AtlasEntityType對(duì)于Attribute類型為另一種EntityType,但是沒(méi)有定義相應(yīng)的relationship,則打印警告信息把所有superType的relationshipAttributes添加到當(dāng)前entityType的relationshipAttributes中AtlasClassificationType把所有的superType允許的entityTypes取交集,得到superTypeEntityTypes;獲取當(dāng)前classificationType允許的entityTypes,記為classificationDefEntityTypes1)若沒(méi)有superType,則entityTypes=classificationDefEntityTypes2)若superTypeEntityTypes isEmpty,則拋異常3)若classificationDefEntityTypes isEmpty,則entityTypes=superTypeEntityTypes4)若superTypeEntityTypes不包含classificationDefEntityTypes,則拋異常5) entityTypes中所有entityType的subType同樣會(huì)被加入entityTypes中
結(jié)語(yǔ)
本文介紹了Atlas元數(shù)據(jù)系統(tǒng)的存儲(chǔ)模型,分別從Atlas架構(gòu),類型系統(tǒng),圖存儲(chǔ)結(jié)構(gòu),類型定義和實(shí)體的圖模型以及類型解析等方面展開(kāi)。希望通過(guò)這篇文章,使大家對(duì)Atlas元數(shù)據(jù)存儲(chǔ)模型會(huì)有更深的了解。
