我使用Spark 1.6.1处理来自CommonCrawl的一些档案。它们来自gzip压缩文本文件,我已经读过Spark必须将这些压缩文件加载到单个分区的RDD中。但是,我在一个由10个节点组成的集群上运行它,每个节点有4个CPU,所以我需要对其进行重新分区以便并行处理数据。这些重新分区步骤看起来似乎是一个不可接受的长时间,当我在任务重新分区步骤的随机写入时间查看Web UI时,它增长到超过40 GB,即使一个.gz存档只有大约100 MB。以下是我正在运行的代码的相关部分:
final WhitelistFilter<String> filter =
new WhitelistFilter<String>(WHITELIST_THRESHOLD, termWeights, regex);
//Each URL points to a gzip-compressed text file in the commoncrawl s3 bucket
//With ~40,000 pages per archive
int counter = 0;
for(String s : ccURL) {
//Obtain WET file from the URL, and filter down to pages of English text
JavaPairRDD<LongWritable, Text> raw =
sc.newAPIHadoopFile("sample.wet.gz",
org.apache.hadoop.mapreduce.lib.input.TextInputFormat.class,
LongWritable.class, Text.class, s3Conf)
.repartition(sc.defaultParallelism() * 3)
JavaRDD<String> pages = JavaPairRDD.fromJavaRDD(
.filter(new WETFilter())
.map(new WETTransformerWithURL())
.filter(filter)).keys();
pages.saveAsTextFile("pages-" + (counter++) + ".txt");
}
过滤器和地图步骤中调用的各种函数只是基本的文本处理 - 最复杂的是根据术语频率分配分数并过滤低于阈值的任何内容。如果我删除对repartition()的调用,整个过程将很快完成,但没有任何并行性。那么重新分区可能会让它变得非常缓慢,并且还让块管理器向磁盘写入数十GB的数据?