Java RDD的最后一项未保存到HDFS

Java RDD的最后一项未保存到HDFS,java,hadoop,apache-spark,hdfs,yarn,Java,Hadoop,Apache Spark,Hdfs,Yarn,我是Spark的新手,目前正在4个Spark Worker上运行一些基本的ETL,从外部源读取项目,然后将它们保存到HDFS。奇怪的是,我的HDFS结果中缺少项目 因为我需要遵循某些文件系统约定,所以我希望将这些项拆分为单独的存储桶,并将它们保存在单独的子文件夹中(我知道我在这里忽略了性能): 列出源代码;//一些字符串列表 JavaRDD任务列表;//每个源都有很多任务 javardditems=taskList.map(任务->新提取器().execute(任务)); for(字符串sour

我是Spark的新手,目前正在4个Spark Worker上运行一些基本的ETL,从外部源读取项目,然后将它们保存到HDFS。奇怪的是,我的HDFS结果中缺少项目

因为我需要遵循某些文件系统约定,所以我希望将这些项拆分为单独的存储桶,并将它们保存在单独的子文件夹中(我知道我在这里忽略了性能):

列出源代码;//一些字符串列表
JavaRDD任务列表;//每个源都有很多任务
javardditems=taskList.map(任务->新提取器().execute(任务));
for(字符串sourceId:sources){
字符串路径=”hdfs:///sources/“+sourceId”;
JavaRDD currentItems=items.filter(
//仅筛选匹配的源ID项
item->item.getSource().equals(sourceId)).map(
//序列化每个筛选项
item->item.toString());
//保存到hdfs
currentItems.saveAsTextFile(“hdfs:///sources/“+sourceId);
}
jsc.stop();//完成
当我在转换/筛选/映射过程中的任何时候调试
.collect().size()
时,都会显示预期/正确的项数。但是,当我在应用程序完成后在HDFS中查看文件时,我只发现每个源中正好有一项比文件中预期的少(我知道Spark将多个项目写入每个part-0000x文件)

有什么想法吗?我不能100%确定是否可能对每个
过滤器(..)重新使用相同的RDD。映射(..)
可能是问题。当我将所有项目转储到同一文件夹中时(对于
shenanigan没有此
),一切都按预期进行。所有项目都已编写。我尝试了
items.cache()
使用当前的解决方案,但这也无济于事

我确实删除了
.filter(..)
操作,并使用一个由2个源组成的小数据集进行测试,每个源提取6项。结果是每个文件夹中有12项,因此
filter(..
)操作显然是罪魁祸首

更新:在深入研究输入源之后,减少源的数量以便于调试,并找出问题是否只在处理的项目多于工作人员时才会出现。代码的一些微小细节可能已经发生了变化,但经过一些轻微的重构和使用越来越多的数据集进行测试之后,我无法再观察到问题解决了(希望永远解决)。如果我发现了原因,我会在这里更新


我正在Hadoop 2.7.2上用Thread运行Spark 1.6.0,我的Spark应用程序是用Java8编写的。该应用程序运行顺利并成功完成。

我认为您的列表
列表源中用于筛选的源ID少于
任务列表中的源ID

如果运行
taskList.map(item->item.getSource()).distinct().count()
它是否等于
sources.size()


如果答案是否,请使用
taskList.map(item->item.getSource()).distinct().collectAsMap()
而不是for循环中的
sources

在编译
taskList
时生成
源列表。大小匹配。我使用较小的数据集和一些调试输出测试了它,2个源,每个源提取6项,操作完成后,我在HDFS中的每个源文件夹中都有5项。我不认为这是一个逻辑错误。一定是RDD及其处理方式有什么特别的地方,我还不知道。如果我删除for循环并将所有项目保存在一个文件夹中,我会得到预期的12个项目。然后我有另一个问题。您的源id对任务执行的次数不变吗?是的。我使用了一些filter开/关和更小的数据集,怀疑如果我提取的项目比工人少,一切都好,只有当我的项目比工人多时问题才会出现。我稳步增加项目并观察结果。我不确定我是否应该高兴或关心报告,现在即使有更多的数据,我也得到了正确的结果……魔鬼在起作用-.-不管怎样。仔细查看来源是个好主意。谢谢你的帮助。如果我知道为什么会发生这种情况,我会更新。
List<String> sources; // some list of strings
JavaRDD<Task> taskList; // a lot of tasks for each source
JavaRDD<Item> items = taskList.map(task -> new Extractor().execute(task));
for (String sourceId : sources) {
  String path = "hdfs:///sources/" + sourceId";
  JavaRDD<String> currentItems = items.filter(
    // filter only matching source ID items
    item -> item.getSource().equals(sourceId)).map(
    // serialise each filtered item
    item -> item.toString());

  // save to hdfs
  currentItems.saveAsTextFile("hdfs:///sources/" + sourceId);
}
jsc.stop(); // done