步骤:
1)从S3(140-200 GB)读取文件。
2)然后我应用filter()函数,以删除记录的大多数映射(将删除大约70%)。
3)对于剩余的记录(总计约40-50 GB),请使用map()创建MyObj的JavaRdd。
4)之后,我使用group by按sesisonId字段对对象进行分组。对于40-50 GB的总空间,我预计groupBy中将有大约300,000个组。
5)然后,对于每个组,我执行processSingeGroupOfEvents()(此函数如下:它需要Interable,然后为每个Iterable进行一些简单的工作(总计300,000个))。
6)之后,我使用coalesce()和saveAsTextFile将结果输出到S3(输出文件大小约为1-2 GB)。
伪代码:
JavaRDD<MyObj> eventsCollection = context.textFile(input)
.filter(data -> applySomeFilter(data)) // This will filter ~70% of records
.map(data -> createMyObjFromData(data));
JavaPairRDD<String, Iterable<MyObj>> eventsCollectionGroupedById = eventsCollection
.groupBy(x -> x.getSessionId())
.persist(StorageLevel.MEMORY_AND_DISK());;
JavaPairRDD<String, String> groupedByIdResults = eventsCollectionGroupedById
.mapValues(iterable -> processSingeGroupOfEvents(iterable, additionalVariable1, additionalVariable2 ));
groupedByIdResults
.coalesce(1) // Union all partitions into single one (in order to avoid multiple output files)
.map(data -> data._2())
.saveAsTextFile(outputS3Location);
我对AWS EMR Spark应用程序的当前配置是:
目前,大约需要30到50分钟才能执行此作业。但是,将来,我希望输入数据的大小将增加一倍(〜300 GB数据=>〜600,000个组,以根据会话ID进行汇总)
我如何估计,如果我的数据加倍,我的集群将能够处理这样的负载?另外,有时我会出错,说r3.8xlarge实例类型超出了我所在区域的配额限制,因此我担心如果添加更多硬件,则会更经常出现此问题。
更新: processSingeGroupOfEvents()方法对具有相同会话ID的事件组(可迭代)进行迭代,并执行一些棘手的计算(例如,计算运行总计,查找组中某些元素的最大值,解析时间戳等)。它会返回逗号分隔的字符串,其中包含特定会话ID的汇总值。
答案 0 :(得分:1)
processSingeGroupOfEvents
是否减少了数据量?如果是,则用groupBy
替换mapValues
和aggregateByKey
可以大大减少要重排的数据量。
之后,我建议您遵循通用的Spark调整指南https://spark.apache.org/docs/latest/tuning.html。检查Spark Web UI的垃圾回收时间。 EMR随Ganglia一起提供,可用于监视群集中的各个节点。节点之间的CPU和内存使用是否均匀?
最后,您可以使用当前的数据量执行作业,但将集群中的节点数减半。如果工作完成但花费了大约两倍的时间,则这是一个很好的信号,表明负载分布均匀并且可能会扩大。如果它崩溃或没有显着降低速度,则说明该工作存在一些严重的瓶颈。