我有3年的数据按year
/ month
/ day
/ hour
进行分区,我想读取所有文件并进行一些处理并将其写回换成具有相同结构的新S3降压器。
如果数据来自s3://spark-old/production/events/2018/12/20/*
,我想在计算完成后将其保存到s3://spark-new/production/events/2018/12/20/*
中。
这些数据已在s3://spark-old/production/events/
和Kinesis
的帮助下被写入FireHose
,因此从技术上讲FireHose决定将数据放在哪个分区中(基于FireHose消耗它们的时间,想!)。
一些要求:
我尝试了几种方法,但都不是完美的方法。
1-编写一个Spark作业(每小时),每小时读取一次,处理数据并将其写回到读取数据的相同路径。然后使用Oozie
或任何其他调度程序来调度从数据开始到现在的每小时作业。由于每个工作都独立于其他工作,因此将Oozie协调器上的并发性提高到14或48或...之类,然后等待所有工作完成。
问题在于,每个小时的时间并不是很大,大部分火花工作都浪费在创建火花会话并在最后将其杀死。处理3年的数据需要很多时间。
2-不是从每个小时读取数据,而是尝试从源3://spark-old/production/events/
读取一天或一个月的数据,并尝试在partitionBy("year", "month", "day", "hour")
的帮助下将其保存回目的地。这种方法存在2个问题
Dataframe.partitionBy.save
时,它将以新格式将数据写入S3路径。 s3://spark-new/production/events/year=2018/month=12/day=20/*
partitionBy("year", "month", "day", "hour")
进行路径分区,而该分区基于server_received_time
(Firehose消耗掉的最接近时间)进行,因此我们无法保证读取的数据从分区A存储到分区B。少量数据移到新分区。3-尝试在单个Spark作业(Spark会话)中读取几个小时(如批处理),并在Spark中以并行方式写回。我仍在尝试确定这是否可行以及这是否是一个好方法。
我想知道什么是满足所有要求的最佳方法。