我有一个非常简单的字数统计程序,可以生成(长,双)计数:
val lines = sc.textFile(directory)
lines.repartition(600).mapPartitions{lineIterator =>
// Generate iterator of (Long,Double) counts
}
.reduceByKey(new HashPartitioner(30), (v1, v2) => v1 + v2).saveAsTextFile(outDir, classOf[GzipCodec])
我的问题:30个分区中的最后一个永远不会被写入。
以下是一些细节:
我可以观察到以下内容:
最后一个日志如下:
15/08/03 23:26:43 INFO SparkHadoopWriter: attempt_201508031748_0002_m_000020_748: Committed
15/08/03 23:26:43 INFO Executor: Finished task 20.0 in stage 2.0 (TID 748). 865 bytes result sent to driver
15/08/03 23:27:50 INFO FileOutputCommitter: Saved output of task 'attempt_201508031748_0002_m_000009_737' to file:/output-dir/_temporary/0/task_201508031748_0002_m_000009
15/08/03 23:27:50 INFO SparkHadoopWriter: attempt_201508031748_0002_m_000009_737: Committed
15/08/03 23:27:50 INFO Executor: Finished task 9.0 in stage 2.0 (TID 737). 865 bytes result sent to driver
15/08/04 02:44:54 INFO BlockManager: Removing broadcast 3
15/08/04 02:44:54 INFO BlockManager: Removing block broadcast_3_piece0
15/08/04 02:44:54 INFO MemoryStore: Block broadcast_3_piece0 of size 2009 dropped from memory (free 611091153849)
15/08/04 02:44:54 INFO BlockManagerMaster: Updated info of block broadcast_3_piece0
15/08/04 02:44:54 INFO BlockManager: Removing block broadcast_3
15/08/04 02:44:54 INFO MemoryStore: Block broadcast_3 of size 3336 dropped from memory (free 611091157185)
15/08/04 02:44:54 INFO BlockManager: Removing broadcast 4
15/08/04 02:44:54 INFO BlockManager: Removing block broadcast_4_piece0
15/08/04 02:44:54 INFO MemoryStore: Block broadcast_4_piece0 of size 2295 dropped from memory (free 611091159480)
15/08/04 02:44:54 INFO BlockManagerMaster: Updated info of block broadcast_4_piece0
15/08/04 02:44:54 INFO BlockManager: Removing block broadcast_4
15/08/04 02:44:54 INFO MemoryStore: Block broadcast_4 of size 4016 dropped from memory (free 611091163496)
想象一下,在两分钟的时间内,对于其他28个分区重复前五行。
我尝试了几件事:
尽管如此,我从来没有从火花中获取最后1/30的数据。有没有人观察过类似的东西?这两个帖子here和here似乎描述了类似的问题但没有解决方案。
更新
永不完成的任务始终是reduceKey + writeToTextFile的第一项任务。我还删除了HashPartitioner,甚至尝试了一个包含400个核心和6000个分区的更大群集。只有5999成功完成,最后一次成功。
UI显示所有任务类似的内容 随机读取大小/记录:20.0 MB / 1954832 但是它显示的第一个(此刻) 随机读取大小/记录:150.1 MB / 711836
数字仍在增长......
答案 0 :(得分:0)
可能是你的钥匙非常歪斜。根据它们的分布方式(或者如果您有一个空键或默认键),大量数据可能会转到单个执行程序,与在本地计算机上运行(加上分布式平台的开销)没有什么不同。它甚至可能导致该机器交换到磁盘,变得无法忍受地慢。
尝试使用aggregateByKey
而不是reduceByKey
,因为它会尝试获取跨执行程序分配的部分和,而不是将所有(可能很大的)键值对集合转移到单个执行程序。并且可以避免将输出分区的数量固定为30以防万一。
编辑:很难检测到问题"它只是没有完成"。你可以做的一件事是引入一个超时:
val result = Await.result(future {
// Your normal computation
}, timeout)
这样,无论任务花费的时间太长,您都可以检测到并在现场收集一些指标。