浅谈元数据采集 | StartDT Tech Lab 10

写在前面

这是奇点云全新技术专栏「StartDT Tech Lab」的第10期。

在这里,我们聚焦数据技术,分享方法论与实战。一线的项目经历,丰富的实践经验,真实的总结体会…滑到文末,可以看到我们的往期内容。

本篇由奇点云DataSimba团队的「元善」和「萤火」带来:

 

作者:元善、萤火

阅读时间:约9分钟

引言

元数据是描述数据的数据。元数据通常包含数据的基本信息和数据血缘信息。

实际业务场景中,业务人员面临数据出现问题后,需要评估影响范围、定位问题环节及责任人的情况。

基于元数据,可分析得到上游问题表、调度任务、下游影响表、影响范围。基于这种有效的评估,企业能更高效地对企业数据资产进行管理。

一、概述

元数据采集可以分为外部系统元数据采集、元数据血缘关系采集,它们都围绕Meta对象体系展开。(如下图所示)

架构图
图源:元善

 

 Meta对象体系 :Meta对象体系是一系列设计良好的元数据API和数据结构,其具备屏蔽复杂特性的能力,可以抽象共性操作。它应用于整个元数据周期,例如:采集期间、分析期间等。所有的元数据行为都围绕它们进行。

 外部系统元数据采集 :应用于外部元数据至Simba元数据的过程。因外部系统存在不同的数据源,其具有特有的访问、存储、序列化等形式。所以我们需要针对不同数据源解析得到有价值的共性信息(例如字段序号、名称、类型、说明等),将其转换为规范统一的内部元数据形式。

 元数据血缘关系采集 :数据经过一系列的调度任务,会生成错综复杂的元数据关系,比如源表、源字段、调度任务、责任人、目标表、目标字段、指标等,我们将这些数据通过Meta对象体系采集存储,为进一步的分析做准备。

下面我们会针对每一个主要模块,简要介绍技术和设计。

二、Meta对象体系

采集元数据首先要设计良好的API规范,我们首先定义了抽象的分区、表、字段、拓展等元数据对象体系,通过不同的数据源Parse解析器,解析成抽象的元数据对象,所有操作围绕对象体系进行。

采集外部元数据-结构图
图源:元善

 - MetaPartition 

分区元数据,包含分区数量、分区字段等信息。

 - MetaTable 

表元数据,包含DB名、表名、表ID、分区标识、创建时间等信息。数据治理通常围绕它展开,也是获得MetaColumn的先决条件。

 - MetaColumn 

字段元数据,包括名称、类型、注释、是否分区字等字段信息。它在数据同步映射、数据指标、数据血缘中都起到重要作用。

 - MetaExtend 

扩展元数据,我们可以通过扩展元数据来支持对更多通用属性的支持,例如总存储、索引大小、访问频次等,这可以帮助我们更好的治理数据。

三、外部元数据采集

对于不同数据源,元数据存储的形式各不相同,对于不同数据源的解析,核心在于定位元数据结构、存储位置。我们以字段元数据(MetaColumn)为例:

 - MySQL Meta Parse 

MySQL字段元数据信息主要存储在information_schema.columns,其中ORDINAL_POSITION、COLUMN_NAME、DATA_TYPE、COLUMN_COMMENT、TABLE_SCHEMA、TABLE_NAME属于关键字段,含义分别是序号、字段名、数据类型、说明、库名、表名。

 - Oracle Meta Parse 

Oracle字段元数据信息主要存储在ALL_TAB_COLUMNS、ALL_COL_COMMENTS中,其中ALL_TAB_COLUMNS.COLUMN_ID、ALL_TAB_COLUMNS.COLUMN_NAME、ALL_TAB_COLUMNS.DATA_TYPE、ALL_COL_COMMENTS.COMMENTS、ALL_TAB_COLUMNS.TABLE_NAME、ALL_TAB_COLUMNS.OWNER属于关键字段,含义分别是序号、字段名、数据类型、说明、表名、所有者。

 - Postgresql Meta Parse 

Postgresql字段元数据信息主要存储在PG_CLASS、PG_ATTRIBUTE、PG_TYPE、PG_NAMESPACE、PG_DESCRIPTION,其中PG_ATTRIBUTE.ATTNUM、PG_ATTRIBUTE.ATTNAME、PG_TYPE.TYPNAME、PG_DESCRIPTION.DESCRIPTION、PG_CLASS.RELNAME、PG_NAMESPACE.NSPNAME属于关键字段,含义分别是序号、字段名、类型、说明、表名、名空间。

 - Impala Meta Parse 

Impala字段元数据信息,可以通过执行“DESCRIBE {表名}”SQL获得。其中NAME(1)、TYPE(2)、COMMENT(3)属于关键字段,含义分别是字段名、类型、含义。

 - Hive Meta Parse 

Hive字段元数据信息,可以通过多种方式读取元数据,例如直接通过SQL读取MySQL元数据、通过HIVE "DESCRIBE FORMATTED"命令集、IMetaStoreClient API。我们着重讲解MySQL元数据存储结构,主要存储在DBS、TBLS、COLUMNS_V2其中关键字段COLUMNS_V2.COLUMN_NAME、COLUMNS_V2.TYPE_NAME、COLUMNS_V2.COMMENT、COLUMNS_V2.INTEGER_IDX、DBS.NAME、COLUMNS_V2.TBL_NAME,含义分别是字段名、类型、含义、序号、库名、表名。

 - Elasticsearch Meta Parse 

Elasticsearch字段元数据信息,可以通过JestClient执行对单表查询语句获得。Elasticsearch采用JSON结构定义表、字段元数据信息。通过解析JSON中mappings字段获得对每个字段的JSON对象,其中KEY、TYPE、INDEX是关键字段,含义分别是字段名、类型、序号。

四、元数据血缘关系采集

DataSimba中的数据血缘信息,往往源于解析生产数据所用的SQL等作业。这里以大数据处理中最常用的离线计算引擎Hive为例,介绍如何通过解析作业的SQL脚本获取数据血缘信息。其他各类计算引擎,例如SparkSQL和FlinkSQL,原理上大同小异。

当收到类似下面的Hive SQL语句

SELECT id, name from t_user where status = 'active' and age > 18

HIVE的处理过程如下:

 01. 语法分析 

使用Antlr将SQL语句解析成抽象语法书(AST),例如:

图源:元善

 

 02. 语义分析 

验证SQL语句中表名、列表、数据类型和隐式转换,以及Hive提供的函数和用户定义函数(UDF/UAF);以及元数据绑定,会从Hive数据库中查询相关元信息,将符号绑定到源表的字段。

 03. 逻辑计划生成 

生成逻辑计划,简单理解就是在单机中可以按照顺序执行抛出结果的计算计划。

 04. 逻辑计划优化 

对算子数进行优化,不改变执行结果的前提下,优化执行计划。常见的例如PartitionPrune,在Hive中定义了分区表,Where条件也出现了分区字段,那么执行时只扫描该分区数据。

 05. 物理计划生成 

将逻辑计划生成包含由MapReduce任务组成的DAG物理计划(Tez、Spark)。会将逻辑计划拆解,生成Mapper和Reducer不同的步骤。

 06. 分布式物理计划执行 

将DAG发送到Hadoop集群执行。

在上面Hive工作流程-语法分析步骤,我们可以通过对AST遍历,得到哪些是输入表,哪些是输出表。例如以下SQL:

insert overwrite table over_tmp select id, age, name from tmp;

输入表: tmp, 输出表: over_tmp

Hive中提供静态血缘解析的支持,通过LineageInfo.getInputTableList() 和LinegeInfo.getOutputTable() 分别可以获得输入表、输出表。

Hive同时也提供支持动态血缘解析,HiveHook拦截Hive执行过程,动态获得关系。血缘采集HiveHook运行于Post-execution hooks过程。在查询执行完成之后以及将结果返回给用户之前调用。我们可以将源表、目标表、源字段、目标字段以及它们的关系发送至MQ,通过集群消费者订阅血缘数据至存储介质。

至此,我们通过本章的学习,简单了解了如何采集外部元数据、构建内部元数据、以及基于Hive的静态/动态血缘采集。当然元数据及以元数据为基础的数据分析,不仅止于此,我们会在之后的学习中继续深入探讨。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一段 C++ 代码,其中包含了一些条件语句和函数调用。逐行解释如下: ```if ( m_env->m_ClearSendQueFlag )``` 如果 `m_env->m_ClearSendQueFlag` 变量为真(非零),则执行下面的代码块。 ```m_asduSendQue.ClearAllDataBuff();``` 调用 `m_asduSendQue` 对象的 `ClearAllDataBuff()` 函数,清空发送队列的所有数据缓冲区。 ```memset(m_sendBuf,0,MaxLen_Buf);``` 使用 `memset()` 函数将 `m_sendBuf` 数组的所有素都设置为 0,该数组的长度为 `MaxLen_Buf`。 ```this->m_env->m_TxBuf.ResetBuf();``` 调用 `m_env` 对象的 `m_TxBuf` 成员的 `ResetBuf()` 函数,重置该成员对象的缓冲区。 ```m_Flag |= IEC104_FLAG_STARTDT;``` 将 `m_Flag` 变量的二进制表示中的第 0 位(从右往左数)设置为 1,表示启动传输(STARTDT)。 ```OutputLogMsgToLogFile("var/log/s104.log",320000,"%s:%d INFO! STARTDT! 104startdtresrt=%d ClearSendQueFlag=%d RtuNo=%d\n",__FILE__,__LINE__,m_env->m_104startdtresrt,m_env->m_ClearSendQueFlag,m_env->m_sRtuNo);``` 调用 `OutputLogMsgToLogFile()` 函数,将日志信息记录到文件中。该函数的第一个参数是文件名,第二个参数是日志文件的最大大小,第三个参数是日志信息的格式化字符串,后面的参数是对应的参数值。 ```this->m_dataTransflag = 0x01;``` 将 `m_dataTransflag` 变量的值设置为 1,表示数据传输。 ```this->m_env->m_appLayer->StartDTProcess();``` 调用 `m_env` 对象的 `m_appLayer` 成员的 `StartDTProcess()` 函数,启动应用层的 STARTDT 过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值