我有以下问题:有一个很大的CSV文件,我们用spark读取。我们需要转换文件的每一行,并将其写回到另一个文本文件。在此转换过程中,我们需要通过REST调用外部服务,并且在编写文件之前,我们需要从服务中获取答案。同时,我们可以在Spark上执行其他操作。
一个简单的实现看起来像这样:
val keys = spark.read.csv("/path/to/myfile.csv")
.map(row => {
val result = new Param(row(0), row(3), row(7))
result
})
.collect()
val enrichedData: Map[String,String] = keys.map(key =>
externalService.getValue(key)) // unpredictable response time
val finalResult = spark.read.csv("/path/to/myfile.csv") // read same file twice
.map(row => doSomeTransformation(row))
.map(row => doSomeMoreTransformation(row))
.map(row => andAnotherCostlyOperation(row))
.map(row => {
val key = row(0)
val myData = enrichedData(key) // only here we use the data from ext.serv.
enrichRow(row, myData)
})
.write.csv("/path/to/output.csv")
这里的问题是我读取相同的输入文件两次。首先,我需要从文件中收集所有密钥,并将它们发送到外部服务。外部服务响应后,我可以再次遍历同一文件,并使用获得的数据来完成对数据的处理。
如何更有效地做到这一点?我直到最后一步才真正需要来自外部服务的数据,因此,如果Spark可以并行执行其他转换,则很好,然后当它到达最后一个map()函数时,它将等待(可能) 0秒)以获取来自外部服务的数据。