TDH集群数据拷贝及元数据迁移

背景:项目中,领导要求定时将生产集群的数据导入到测试集群中,以便于数据开发人员进行开发,其次也能起到一个备份的作用;

我们调研了一下,觉得distcp应该是集群同步最快的方式了,因而决定用distcp 命令来进行集群间的文件拷贝,但文件导过去后,因为都是orc表,虽然文件导过去了,但是数据依然不可使用;所以决定一不做二不休,直接将元数据也一把干过去;

集群环境:TDH6.0.2

 

我们准备分两步进行:

1、全量同步 集群文件 和 元数据

2、其后每日增量同步集群文件和元数据

首先第一步,挑一个黄道吉日,将文件按库逐步全量同步到测试环境;

hadoop distcp -pb hdfs://node4:8020/inceptor1/user/hive/warehouse/ods.db/hbxyoper hdfs://tdh1:8020/inceptor1/user/hive/warehouse/ods.db/

这一步非常耗时,而且一旦开始集群间拷贝,会非常占带宽,虽然是万兆带宽,但是依然会长时间占满,有可能影响业务系统,因而建议在周末同步,或者加 -bandwidth 来限制带宽。

 

第二步,我们则打算通过java程序来实现数据和元数据的自动同步

首先来说,其实数据文件其实很好同步,只要通过程序调度一下hadoop命令即可,但是文件的拷贝过程,增量同步的最细粒度只能做到按分区同步;

所以我们决定对集群中的非分区表每日全量同步,分区表则按日期增量抽取(正常来说,大表一般都会进行分区);

有些难度的是元数据的增量同步,经过梳理和测试,我们发现要想完全从生产集群”拷贝”一张表到测试环境,至少需要同步13张核心表;

  1. TBLS(该表中存储Hive表、视图、索引表的基本信息

TBL_ID

ID

 CREATE_TIME

创建时间

 DB_ID

数据库ID (对应DBSDB_ID)

LAST_ACCESS_TIME

上次访问时间

OWNER

所有者

RETENTION

保留字段

 SD_ID

序列化配置信息(对应SDS表中的SD_ID

TBL_NAME

表名

TBL_TYPE

表类型

VIEW_EXPANDED_TEXT

视图详细的HQL语句

VIEW_ORIGINAL_TEXT

视图原始的HQL语句

2、TABLE_PARAMS(表/视图的属性信息)

字段

描述

TBL_ID

ID(对应TBLS中的TBL_ID

PARAM_KEY

属性名

PARAM_VALUES

属性值

3、TBL_PRIVS(存储表/视图的权限信息)

 

字段

描述

TBL_GRANT_ID

ID(对应TBLS中的TBL_ID

CREATE_TIME

 

GRANT_OPTION

 

GRANTOR

 

GRANTOR_TYPE

 

PRINCIPAL_TYPE

用户类型

TBL_PRIV

权限

TBL_ID

ID(对应TBLS中的TBL_ID

4、SDS(文件存储的基本信息 ,如:存储格式,路径,分桶,是否压缩等信息)

SD_ID

 

CD_ID

字段信息ID

INPUT_FORMAT

文件输入格式

IS_COMPRESSED

是否压缩

IS_STOREDASSUBDIRECTORIES

是否以子目录存储

LOCATION

HDFS路径

 NUM_BUCKETS

分桶数量

 OUTPUT_FORMAT

文件输出格式

SERDE_ID

序列化类ID

5、SERDE_PARAMS(存储序列化的一些属性、格式信息,比如:行、列分隔符)

字段

描述

SERDE_ID

序列化类配置ID(对应SERDESSERDE_ID

PARAM_KEY

属性名

PARAM_VALUE

属性值

6、SERDES(存储Hive存储的属性信息 存储序列化使用的类信息)

字段

字段说明

SERDE_ID

序列化类配置ID(对应SDSSERDE_ID

NAME

序列化类别名

SLIB

序列化类

 

7、columns_v2(表的字段信息)

字段

字段说明

CD_ID

字段信息ID(对应表SDSCD_ID

COMMENT

字段注释

COLUMN_NAME

字段名

TYPE_NAME   

字段类型

INTEGER_IDX

字段顺序

8、PARTITIONS(分区的基本信息)

字段

字段说明 

PART_ID

 分区ID

CREATE_TIME

 分区创建时间

LAST_ACCESS_TIME

 最后一次访问时间

PART_NAME

 分区名称

SD_ID

 分区存储ID

 TBL_ID

 ID,对应TBLSTBL_ID

9、partition_keys(分区的字段信息)

字段名称

字段说明

TBL_ID

ID,对应TBLSTBL_ID

PKEY_COMMENT

分区字段说明

PKEY_NAME

分区字段名称

PKEY_TYPE

分区字段类型

INTEGER_IDX

分区字段顺序

10、partition_key_vals(分区字段值)

字段

字段说明

PART_ID

分区ID,对应PARTITIONS的PART_ID

PART_KEY_VAL

分区字段值

INTEGER_IDX

分区字段值顺序

11、partition_params(分区的属性信息)

字段

字段说明

PART_ID

分区ID,对应PARTITIONS的PART_ID

PARAM_KEY

分区属性名

PARAM_VALUE

分区属性值

12、BUCKETING_COLS()

字段

字段说明

SD_ID

 

BUCKET_COL_NAME

分桶字段名

INTEGER_IDX

 

13、CDS ()

字段

字段说明

CD_ID

对应SDSCD_ID

需要注意的是:TBLS的SD_ID和SD_ID并不完全对应,需要获取TBLS的SD_ID查出SDS的CD_ID,再根据拿到的CD_ID反查出SDS中对应的SD_ID和SERDE_ID; 这样才能获取完整的数据;

 

在这一步,要注意的是这13张表之中存在着外键关系,因而无论是删除还是插入,都要注意其先后顺序,否则会导致无法删除或插入;

但是后面我们从mysqldump中受到了启发,又发现了一种新的方式可以不受外键之间的关系,任意的删除和插入数据:

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

在session中,添加这条命令,即可忽略外键;

到这一步,基本元数据和数据文件都已能成功落到测试环境上了;

不过我们在这里遇到了一个巨坑,虽然元数据看上去已经成功落入到测试的元数据库中,但是在hive上我们依然不能访问到数据;

我们简单比对了一下生产和测试的元数据,发现二者几乎一致;

到这一步,我们一度以为可能同步元数据过程中,不止需要同步12张,可能还是缺少了某一张“关键”的表,我们花费了大量的时间去比对了一下,基本确定了,除了这12张表,其他的表只要初始化过来,之后基本不用同步;

至此,场面一度陷入僵局,不得已之下,我们直接将两个元数据库的数据直接dump出来,比较两个dump文件,最终发现了metastore_inceptor1.TBLS 表中的stargate_table_code 字段不一致

生产截图:

测试截图:

至此我们才发现这个巨坑的问题:

那就是mysql会把tinyint(1) 类型当成boolean返回,所以 -1 无法被转换,插入到测试库中会变为null值;

其实到这步解决方式比较多了,可以在程序里多加一个类型转换,不过我们没采用这种方式。

我们的解决方案是:在jdbc的连接中加上?tinyInt1isBit=false&transformedBitIsBoolean=false; 例:jdbc:mysql://node1:3316/metastore_inceptor1?tinyInt1isBit=false&transformedBitIsBoolean=false

这样同样可以解决tinyint会被转换成boolean类型的问题;

 

此时重新同步元数据,就不会有问题了,数据也可以正常访问了;

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值