Flink源码分析之深度解读流式数据写入hive

本文深入探讨Flink如何将流式数据高效写入Hive,涵盖数据流处理、写入格式判断、分区提交策略等关键环节,解析StreamingFileWriter与StreamingFileCommitter的运作机制。

前言

前段时间我们讲解了flink1.11中如何将流式数据写入文件系统和hive [flink 1.11 使用sql将流式数据写入hive],今天我们来从源码的角度深入分析一下。以便朋友们对flink流式数据写入hive有一个深入的了解,以及在出现问题的时候知道该怎么调试。

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

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

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

写入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模式的,数据是可分区的、并且数据是可以被覆盖写的。

类里面的这些变量,看名字就大概知道是什么意思了,就不做解释了,讲一下HiveShim,我们在构造方法里看到hiveShim是和hive 的版本有关的,所以其实这个类我们可以理解为对不同hive版本操作的一层封装。

hiveShim = HiveShimLoader.loadHiveShim(hiveVersion);
java flink是一个高性能的分布式流式计算框架,可以实现大规模的数据处理和分析。而hive是一个分布式数据仓库工具,可以用于存储和查询大规模的结构化数据。redis是一个高性能的内存数据库,可以用于存储和检索数据。 要实现java flink读取hive表中的数据写入redis,我们可以按照以下步骤进行操作: 1. 在java flink中,首先需要配置并连接到hive数据库。可以使用FlinkHiveCatalog来创建一个连接到Hive的catalog,并设置相关的hive metastore地址、用户名和密码等。 2. 根据需要,编flink程序来读取hive表的数据。可以使用flink的DataStream或Table API来读取hive数据,并将其转换为适当的数据或表。 3. 在准备好数据之后,我们可以使用flink的RedisSink来将数据写入redis中。在使用RedisSink之前,需要先引入flink-connector-redis的依赖包,并在flink配置文件中配置好redis的连接参数,如redis的主机地址、端口号、密码等。 4. 编代码将数据写入redis。可以根据数据的特点,选择将整个数据写入一个redis数据结构中,或者将数据分解为多个key-value对存储到redis中。 5. 在代码编完成后,我们可以使用flink提供的命令或者IDE工具来运行flink程序,它会自动连接到hive数据库和redis,并完成数据的读取和写入。 通过以上步骤,java flink就可以实现读取hive表中的数据写入redis。这样可以通过flink的分布式计算和hive数据存储能力,结合redis的高速读能力,实现大规模数据的处理和查询。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值