1、Null存储一致性的问题
hive中的Null在底层是以 "\N"来存储的,而MySQL的Null中在底层就是Null,为了保证数据两端的一致性:
(1)在导出数据时采用:–input-null-string和–input-null-non-string两个参数。
(2)在导入数据时采用:–null-string和–null-non-string两个参数。
2、部分Map任务失败
2.1、实际业务问题:数据前后不一致
Sqoop导出数据到MySQL时,使用4个Map任务,过程会有2个任务失败,那此时MySQL中存储了另外两个Map任务导入数据。而开发工程师发现任务失败后,会调试问题并最终全部数据正确导入Mysql,那后面老板再次看报表数据,发现本次看到的数据和之前的不一致,在在生产环境坚决是不允许的;
2.2、解决方案之一:分级表解决
(1)由于Sqoop将导出过程分解为多个事务,因此失败的作业导出作业会导致部分数据提交数据库中。在某些情况,这可能会进一步导致后续作业插入冲突而失败,或者在其他情况下导致重复数据。
(2)可以通过指定一个分级表来解决这个问题,该表示一个辅助表,用于对导出数据进行阶段化。分阶段的数据最终在到单个事务中移动到目标表。这四个临时表如果有一个表导出数据有问题,则全部会回滚。
- 详细方案说明
#具体代码
sqoop export
--connect jdbc:mysql://192.168.137.10:3306/user_behavior
--user_name root
--password 123456
--table app_cource_study
--columns watch_cnt,dt
--fields-terminated-by "\t"
--export-dir "user/hive/warehouse/tmp.db/app_cource_syudy_analsis_${day}"
--staging-table app_cource_studay_emp
--clear-staging-table #任务开始前,清空表
--input-null-string '\N'
- 细节说明
参数说明:--staging-table <staging-table-name> 中间表
--clear-staging-string 任务开始前清空表
细节处阐述:
传输过程中数据暂存临时表中,最终临时表中的数据将被move到目标表中;
临时表为mysql中的临时表
2.3、解决方案二:设置map数量为1个
设置map数量为1个,真实生产环境下不可能。
设置多个map任务时,采用-staging-table方式,仍然可以解决数据一种性问题。
3、数据传输的脏数据处理方式
3.1、临时表
使用临时表缓存数据,然后在一个事务中将临时表的数据move到目的表;
3.2、自定义回滚
通过用户自定义语句/方法(触发器等),在任务失败后,执行清除数据操作;
3.3、传输任务的幂等性
如果一个任务失败了,产生了脏数据,解决问题后,在跑一次任务,能够最终正确,例如hive写入使用INSERT OVERWRITE
(insert into 与insert overwrite 都可以向hive表中插入数据,但是insert into 直接追加到表中数据的尾部,
insert overwrite会重复写数据,即先进行删除,再写入,如果存在分区情况,insert overwrite只重写当前分区数据)
4、Sqoop数据导出Parquet格式数据
4.1、实际开发问题
Ads层数据用Sqoop往MySql中导入数据的时候,如果用了orc(Parquet)不能导入,需转化成text格式
4.2、解决方案
(1)创建text临时表:把Parquet中表数据导入到临时表,把临时表导出到目标表用于可视化
(2)ads层建表的时候就不要建Parquet表