我们有一个用例,在一些流数据之上运行用spark编写的ETL,ETL每小时将结果写入目标配置单元表,但用户通常会对目标表运行查询,我们也遇到过由于spark同时加载表而导致查询错误的情况。我们有什么替代方案来避免或最大限度地减少这种错误?火花作业(或配置单元表(有任何属性吗?或者创建一个临时表之类的东西?
错误为:
java.io.FileNotFoundException:文件不存在[HDFS PATH]
我认为发生这种情况是因为元数据显示有一个文件a在作业执行过程中被删除。
该表按年、月、日进行分区(使用HDFS作为存储(,每次ETL运行时,它只更新(通过分区覆盖(当前日期分区。目前没有";事务性的";集群中启用了表(即使我在测试集群上测试了用例,也没有运气(
简单的选择是使用一种表格式,该格式旨在处理并发读写,如hudi或delta lake。更复杂的版本涉及使用编写器写入的分区的仅追加表。完成后,编写器更新视图以指向新数据。另一种可能的选择是在插入时对表进行分区。
有一组两个表和它们的视图:
CREATE TABLE foo_a (...);
CREATE TABLE foo_b (...);
CREATE VIEW foo AS SELECT x, y, z, ... FROM foo_a;
ETL过程的第一次迭代需要:
- 同步
foo_a
->foo_b
- 做
foo_b
上的工作 - 删除视图
foo
并重新创建指向foo_b
的视图
在第3步之前,用户查询将针对表foo_a
运行。从切换的那一刻起,它们就与foo_b
对抗。ETL的下一次迭代将以相反的方式工作。
这并不完美。ETL中需要双倍的存储空间和一些额外的复杂性。无论如何,如果
- 用户运气不好,在掉落和重新创建视图
- 用户提交的查询足够重,可以运行两次ETL迭代
不确定,但请查看
创建表foo_a(…(;CREATE TABLE foo_b(…(;