通过源码分析Flink如何流式数据写入hive

本文深入探讨了Flink如何通过源码实现流式数据写入Hive,包括获取Hive基本信息、流处理逻辑、分区处理、写入格式判断等关键步骤。详细分析了HiveTableSink、StreamingFileSink和StreamingFileWriter的工作原理,以及分区提交策略和触发器。最后,讨论了在实际操作中可能遇到的挑战和问题。
摘要由CSDN通过智能技术生成

前言

我们来从源码的角度深入分析一下。以便朋友们对flink流式数据写入hive有一个深入的了解,以及在出现问题的时候知道该怎么调试。

其实我们可以想一下这个工作大概是什么流程,首先要写入hive,我们首先要从hive的元数据里拿到相关的hive表的信息,比如存储的路径是哪里,以便往那个目录写数据,还有存储的格式是什么,orc还是parquet,这样我们需要调用对应的实现类来进行写入,其次这个表是否是分区表,写入数据是动态分区还是静态分区,这些都会根据场景的不同而选择不同的写入策略。

写入数据的时候肯定不会把所有数据写入一个文件,那么文件的滚动策略是什么呢?写完了数据我们如何更新hive的元数据信息,以便我们可以及时读取到相应的数据呢?

我画了一个简单的流程图,大家可以先看下,接下来我们带着这些疑问,一步步的从源码里探索这些功能是如何实现的。

在这里插入图片描述

数据流处理

我们这次主要是分析flink如何将类似kafka的流式数据写入到hive表,我们先来一段简单的代码:

//构造hive catalog
  String name = "myhive";
  String defaultDatabase = "default";
  String hiveConfDir = "/Users/user/work/hive/conf"; // a local path
  String version = "3.1.2";
  HiveCatalog hive = new HiveCatalog(name, defaultDatabase, hiveConfDir, version);  tEnv.registerCatalog("myhive", hive);
  tEnv.useCatalog("myhive");
  tEnv.getConfig().setSqlDialect(SqlDialect.HIVE);  tEnv.useDatabase("db1");
  tEnv.createTemporaryView("kafka_source_table", dataStream);
  String insertSql = "insert into  hive.db1.fs_table SELECT userId, amount, " +
                     " DATE_FORMAT(ts, 'yyyy-MM-dd'), DATE_FORMAT(ts, 'HH'), DATE_FORMAT(ts, 'mm') FROM kafka_source_table";
  tEnv.executeSql(insertSql);

系统在启动的时候会首先解析sql,获取相应的属性,然后会通过java的SPI机制加载TableFactory的所有子类,包含TableSourceFactory和TableSinkFactory,之后,会根据从sql中解析的属性循环判断使用哪个工厂类,具体的操作是在TableFactoryUtil类的方法里面实现的。

比如对于上面的sql,解析之后,发现是要写入一个表名为hive.db1.fs_table的hive sink。所以系统在调用TableFactoryUtil#findAndCreateTableSink(TableSinkFactory.Context context)方法以后,得到了TableSinkFactory的子类HiveTableFactory,然后调用相应的createTableSink方法来创建相应的sink,也就是HiveTableSink。

我们来简单看下HiveTableSink的变量和结构。

/**
 * Table sink to write to Hive tables.
 */
public class HiveTableSink implements AppendStreamTableSink, PartitionableTableSink, OverwritableTableSink {
 private static final Logger LOG = LoggerFactory.getLogger(HiveTableSink.class);
 private final boolean userMrWriter;
 //是否有界,用来区分是批处理还是流处理
 private final boolean isBounded;
 private final JobConf jobConf;
 private final CatalogTable catalogTable;
 private final ObjectIdentifier identifier;
 private final TableSchema tableSchema;
 private final String hiveVersion;
 private final HiveShim hiveShim;
 private LinkedHashMap<String, String> staticPartitionSpec = new LinkedHashMap<>();
 private boolean overwrite = false;
 private boolean dynamicGrouping = false;

我们看到它实现了AppendStreamTableSink, PartitionableTableSink, OverwritableTableSink三个接口,这三个接口决定了hive sink实现的功能,数据只能是append模式的,数据是可分区的、并且数据是可以被覆盖写的。

类里面的这些变量,看名字就大概知道是什么意思了,就不做解释

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值