You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在同一AWS EMR集群中并发运行Spark作业?可行性及实现细节

在同一AWS EMR集群中并发运行Spark作业:可行性与实操指南

当然没问题!AWS EMR完全支持在同一个集群上并发运行多个Spark作业——不管是批量处理任务还是交互式分析,只要做好资源调度配置和作业参数优化,就能让多个作业高效共享集群资源,互不干扰。下面我就详细拆解可行性、实现方法和具体操作步骤:

一、核心原理:YARN调度器的关键作用

EMR默认采用YARN作为资源管理器,所有Spark作业都运行在YARN框架之上。YARN的调度器(主要是Capacity SchedulerFair Scheduler)就像集群的「资源调度管家」,负责把CPU、内存等资源合理分配给多个并发作业,避免单个作业占用全部资源导致其他任务饥饿。

  • Capacity Scheduler是EMR的默认选项,适合多租户场景,你可以把集群资源划分为多个队列,每个队列分配固定的资源容量,作业提交到指定队列后,队列内还能配置并发作业数。
  • Fair Scheduler则更灵活,不需要预先划分固定资源容量,作业会动态公平地共享集群资源,适合资源需求波动较大的场景。

二、具体实现方法

1. 选择并配置合适的YARN调度器

(1)Capacity Scheduler(默认推荐)

如果你是多团队共享集群,或者作业资源需求相对固定,用这个调度器最省心:

  • 可以在EMR集群创建时,通过「配置分类」里的yarn-site来定义队列,比如新增一个专门的Spark作业队列:
    <property>
      <name>yarn.scheduler.capacity.root.queues</name>
      <value>default,spark_prod</value> <!-- 新增spark_prod队列 -->
    </property>
    <property>
      <name>yarn.scheduler.capacity.root.spark_prod.capacity</name>
      <value>60</value> <!-- 该队列占集群总资源的60% -->
    </property>
    <property>
      <name>yarn.scheduler.capacity.root.spark_prod.maximum-capacity</name>
      <value>80</value> <!-- 峰值时最多占用80%资源 -->
    </property>
    
  • 也可以在集群运行时修改配置,然后重启YARN资源管理器生效:
    sudo stop-yarn-resourcemanager && sudo start-yarn-resourcemanager
    

(2)Fair Scheduler(灵活场景)

如果你的作业资源需求波动大,或者希望作业能动态共享资源,可以切换到Fair Scheduler:

  • 在EMR集群创建时,修改yarn-site配置:
    <property>
      <name>yarn.resourcemanager.scheduler.class</name>
      <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
    </property>
    <property>
      <name>yarn.scheduler.fair.allocation.file</name>
      <value>/etc/hadoop/conf/fair-scheduler.xml</value> <!-- 指定调度器配置文件路径 -->
    </property>
    
  • 然后编写fair-scheduler.xml来定义队列、资源权重等规则,比如:
    <allocations>
      <queue name="spark">
        <weight>2</weight> <!-- 资源权重是default队列的2倍 -->
        <maxRunningApps>10</maxRunningApps> <!-- 最多同时运行10个作业 -->
      </queue>
    </allocations>
    

2. 为Spark作业配置合理的资源参数

每个Spark作业提交时,一定要明确设置资源参数,避免单个作业把集群资源吃光:

  • 驱动程序资源:--driver-memory(驱动内存)、--driver-cores(驱动CPU核数)
  • 执行器资源:--executor-memory(每个执行器内存)、--executor-cores(每个执行器CPU核数)、--num-executors(执行器数量)
  • 还可以用spark.yarn.queue指定作业提交的目标队列(对应YARN的队列配置)

举个提交作业的命令示例:

spark-submit \
  --class com.example.MyBatchJob \
  --master yarn \
  --deploy-mode cluster \
  --queue spark_prod \
  --driver-memory 2G \
  --executor-memory 4G \
  --executor-cores 2 \
  --num-executors 5 \
  s3://my-bucket/spark-jobs/my-job.jar

3. 启用Spark动态资源分配(推荐)

动态资源分配允许Spark作业根据负载自动增减执行器数量,这样多个作业能更高效地共享资源,避免闲置浪费:

  • 你可以在EMR集群创建时,通过spark-defaults配置分类全局开启:
    spark.dynamicAllocation.enabled=true
    spark.shuffle.service.enabled=true
    
  • 也可以在单个作业提交时临时指定:
    spark-submit \
      --conf spark.dynamicAllocation.enabled=true \
      --conf spark.shuffle.service.enabled=true \
      # 其他作业参数...
    
    注:EMR默认已经配置了YARN的shuffle服务,所以开启这个功能不需要额外部署。

4. 交互式作业的并发处理

如果是用EMR Notebook、Spark Shell或者Zeppelin运行交互式作业,同样可以并发执行:

  • 比如打开多个EMR Notebook实例,每个实例对应一个独立的Spark应用,YARN会自动为它们分配资源(只要集群有剩余资源)
  • 注意给每个交互式作业设置合理的资源上限,比如在Notebook的Spark配置里限制executor-memorynum-executors,避免影响批量作业。

三、并发运行的实操步骤

假设你已经有一个运行中的EMR集群,按以下步骤提交并发作业:

  1. (可选)配置YARN队列
    按照上面Capacity Scheduler的配置方法,新增一个spark_prod队列并分配资源,重启YARN生效。

  2. 提交第一个Spark作业
    spark-submit提交第一个批量作业,指定队列和资源参数:

    spark-submit \
      --class com.job.UserBehaviorAnalysis \
      --master yarn \
      --deploy-mode cluster \
      --queue spark_prod \
      --executor-memory 3G \
      --executor-cores 2 \
      --num-executors 4 \
      s3://my-job-bucket/jobs/user-behavior.jar
    
  3. 提交第二个Spark作业
    不需要等待第一个作业完成,直接提交第二个作业,同样指定队列和合理的资源:

    spark-submit \
      --class com.job.SalesDataAggregation \
      --master yarn \
      --deploy-mode cluster \
      --queue spark_prod \
      --executor-memory 3G \
      --executor-cores 2 \
      --num-executors 4 \
      s3://my-job-bucket/jobs/sales-agg.jar
    
  4. 监控并发作业状态

    • 登录EMR控制台,进入集群详情页的「Applications」标签,就能看到所有运行中的Spark作业
    • 也可以直接访问YARN ResourceManager的UI(EMR主节点的8088端口),查看每个作业的资源分配、运行进度和日志。

四、关键注意事项

  • 资源隔离:确保所有并发作业的资源请求总和不超过集群总资源,比如集群总内存是64G,就不要让两个作业都请求40G内存
  • 队列优先级:可以给重要队列设置更高优先级,比如在Capacity Scheduler里配置yarn.scheduler.capacity.root.spark_prod.priority,让核心作业优先获取资源
  • 数据冲突:如果多个作业访问同一外部数据源(比如S3上的同一份文件),要注意处理并发读写,避免数据不一致
  • EMR版本适配:不同EMR版本的默认配置有差异,比如EMR 6.x+对Spark 3.x的支持更完善,动态资源分配的默认设置更合理,建议使用较新的稳定版本。

内容的提问来源于stack exchange,提问作者Kunal

火山引擎 最新活动