我正在Spark群集上分发一些下载任务。输入来自一个源,它不能总是使用Spark的常规方法(如parallelize
或textFile
等)进行并行化。相反,我有一个服务为我提供了一堆下载任务(URL +封装逻辑来读取和解密它),我使用parallelize
分发。
当有几千个任务时,Spark会将任务平均分配给所有从属服务器,从而实现最高级别的并行性。但是,当有几百个任务时,Spark认为数据集很小,只能在少数从站上计算,以减少通信时间并增加数据局部性。但在我的情况下这是错误的,每个任务都可以生成数千个JSON记录,我希望下载能够在我的群集中使用尽可能多的计算机执行。
目前我有两个想法:
repartition
将分区数设置为核心数repartition
将分区数设置为数字下载任务我不喜欢第一个,因为我必须在我的代码中传递核心数量,而这些核心目前不需要知道它有多少资源。我一次只运行一个Spark作业,但将来我可能会有更多这些,所以我实际上必须通过核心数除以我想在集群上运行的并行作业数。我不喜欢第二个,因为当我只有40个节点时,划分成数千个分区似乎很尴尬。
有没有办法告诉Spark尽可能多地分发RDD的元素?如果没有,两个选项中的哪一个是可取的?
答案 0 :(得分:1)
如果每次下载都可以产生大量记录,并且您没有大量下载(只有几千次),我建议每次下载创建一个分区。
安排几千个任务的总开销只有几秒钟。我们通常会生产数以万计的分区。
如果您在一个分区中有多个下载,则最终可能会遇到非常大的分区。如果您的分区无法完全适合可用内存两次,那么您将遇到一些操作问题。例如,整个分区的join
和distinct
构建哈希表。
您不应该使用repartition
。 parallelize
采用第二个参数,即所需的分区数。虽然URL列表不是大量数据,但如果您只是创建具有正确数量的分区的RDD,而不是在创建之后对其进行混洗,那么它会更好。