需求

公司里有两个部门,一个叫hive,一个叫pig,这两个部门都需要使用公司里的hadoop集群。于是问题来了,因为hadoop默认是FIFO调度的,谁先提交任务,谁先被处理,于是hive部门很担心pig这个部门提交一个耗时的任务,影响了hive的业务,hive希望可以和pig在高峰期时,平均使用整个集群的计算容量,互不影响。

思路

hadoop的默认调度器是FIFO,但是也有计算容量调度器,这个调度器可以解决上述问题。可以在hadoop里配置三个队列,一个是default,一个是hive,一个是pig。他们的计算容量分别是30%,40%,30%.这样hive和pig这两个部门,分为使用hive和pig两个队列,其中default作为其他部门或者临时使用。但是,如果hive部门和pig部门又希望,在平常时,没有人用集群的时候,hive或者部门可以使用100%的计算容量。

解决方法

修改hadoop的配置文件mapred-site.xml:


hadoop默认的late算法 hadoop默认调度_ci



<property> 
  <name>mapred.jobtracker.taskScheduler</name> 
  <value>org.apache.hadoop.mapred.CapacityTaskScheduler</value> 
</property> 
<property> 
  <name>mapred.queue.names</name> 
  <value>default,hive,pig</value> 
</property>



hadoop默认的late算法 hadoop默认调度_ci


 

在capacity-scheduler.xml文件中填写如下内容:


hadoop默认的late算法 hadoop默认调度_ci



<property>
    <name>mapred.capacity-scheduler.queue.hive.capacity</name>
    <value>40</value>
    <description>Percentage of the number of slots in the cluster that are
      to be available for jobs in this queue.
    </description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.hive.maximum-capacity</name>
    <value>-1</value>
    <description>
    </description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.hive.supports-priority</name>
    <value>true</value>
    <description></description>
  </property>
  
    <property>
    <name>mapred.capacity-scheduler.queue.hive.minimum-user-limit-percent</name>
    <value>100</value>
    <description> </description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.hive.user-limit-factor</name>
    <value>3</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.hive.maximum-initialized-active-tasks</name>
    <value>200000</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.hive.maximum-initialized-active-tasks-per-user</name>
    <value>100000</value>
    <description></description>
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.hive.init-accept-jobs-factor</name>
    <value>10</value>
    <description></description>
  </property>
  
<!-- pig -->
<property>
    <name>mapred.capacity-scheduler.queue.pig.capacity</name>
    <value>30</value>
    <description></description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.pig.maximum-capacity</name>
    <value>-1</value>
    <description></description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.pig.supports-priority</name>
    <value>true</value>
    <description>If true, priorities of jobs will be taken into 
      account in scheduling decisions.
    </description>
  </property>
  
    <property>
    <name>mapred.capacity-scheduler.queue.pig.minimum-user-limit-percent</name>
    <value>100</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.pig.user-limit-factor</name>
    <value>4</value>
    <description>The multiple of the queue capacity which can be configured to
    allow a single user to acquire more slots.
    </description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.pig.maximum-initialized-active-tasks</name>
    <value>200000</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.pig.maximum-initialized-active-tasks-per-user</name>
    <value>100000</value>
    <description></description>
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.pig.init-accept-jobs-factor</name>
    <value>10</value>
    <description></description>
  </property>

<!-- default --> 
  <property>
    <name>mapred.capacity-scheduler.queue.default.capacity</name>
    <value>30</value>
    <description></description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.default.maximum-capacity</name>
    <value>-1</value>
    <description></description>    
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.default.supports-priority</name>
    <value>true</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.default.minimum-user-limit-percent</name>
    <value>100</value>
    <description></description>
  </property>
  
  <property>
    <name>mapred.capacity-scheduler.queue.default.user-limit-factor</name>
    <value>4</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.default.maximum-initialized-active-tasks</name>
    <value>200000</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.default.maximum-initialized-active-tasks-per-user</name>
    <value>100000</value>
    <description></description>
  </property>

  <property>
    <name>mapred.capacity-scheduler.queue.default.init-accept-jobs-factor</name>
    <value>10</value>
    <description></description>
  </property>
---Hadoop计算能力调度器算法解析(转)
1. 编写目的本文描述了hadoop中的计算能力调度器(Capacity Scheduler)的实现算法,计算能力调度器是由Yahoo贡献的,主要是解决HADOOP-3421中提出的,在调度器上完成HOD(Hadoop On Demand)功能,克服已有HOD的性能低效的缺点。它适合于多用户共享集群的环境的调度器。本文解析的计算能力调度器属于Hadoop 0.20.2。本文组织结构如 下:1)编写目的 2)计算能力调度器介绍 3)计算能力调度器算法分析 4)计算能力调度器源代码分析 5)计算能力调度器与公平调度器比较 6)参考资料。2. 计算能力调度器介绍Capacity Scheduler支持以下特性:(1) 计算能力保证。支持多个队列,某个作业可被提交到某一个队列中。每个队列会配置一定比例的计算资源,且所有提交到队列中的作业共享该队列中的资源。(2) 灵活性。空闲资源会被分配给那些未达到资源使用上限的队列,当某个未达到资源的队列需要资源时,一旦出现空闲资源资源,便会分配给他们。(3) 支持优先级。队列支持作业优先级调度(默认是FIFO)(4) 多重租赁。综合考虑多种约束防止单个作业、用户或者队列独占队列或者集群中的资源。(5) 基于资源的调度。 支持资源密集型作业,允许作业使用的资源量高于默认值,进而可容纳不同资源需求的作业。不过,当前仅支持内存资源的调度。3. 计算能力调度器算法分析3.1 涉及到的变量在capacity中,存在三种粒度的对象,分别为:queue、job和task,它们均需要维护的一些信息:(1) queue维护的信息@ queueName:queue的名称@ ulMin:每个用户的可用的最少资源量(所有用户均相同),需用户在配置文件中指定@ capacityPercent:计算资源比例,需用户在配置文件中指定@ numJobsByUser:每个用户的作业量,用以跟踪每个用户提交的作业量,并进行数量的上限限制。该队列中map 或reduce task的属性:@ capacity:实际的计算资源量,这个随着tasktracker中slot数目变化(用户可能在添加或减少机器节点)而动态变化,大小为:capacityPercent*mapClusterCapacity/100@ numRunningTasks:正在running的task数目@ numSlotsOccupied:正在running的task占用的slot总数,注意,在Capacity Scheduler中,running task与slot不一定是一一对应的,每个task可获取多个slot,这主要是因为该调度支持内存资源调度,某个task可能需要多个slot包含的内存量。@ numSlotsOccupiedByUser:每个用户的作业占用slot总数,用以限制用户使用的资源量。(2) job维护的信息priority:作业优先级,分为五个等级,从大到小依次为:VERY_HIGH,HIGH,NORMAL,LOW,VERY_LOW;numMapTasks/ numReduceTasks :job的map/reduce task总数runningMapTasks/ runningMapTasks:job正在运行的map/reduce task数finishedMapTasks/finishedReduceTasks:job已完成的map/reduce task数……(3) task维护的信息task开始运行时间,当前状态等3.2 计算能力调度算法当某个tasktracker上出现空闲slot时,调度器依次选择一个queue、(选中的queue中的)job、(选中的job中的)task,并将该slot分配给该task。下面介绍选择queue、job和task所采用的策略:(1) 选择queue:将所有queue按照资源使用率(numSlotsOccupied/capacity)由小到大排序,依次进行处理,直到找到一个合适的job。(2) 选择job:在当前queue中,所有作业按照作业提交时间和作业优先级进行排序(假设开启支持优先级调度功能,默认不支持,需要在配置文件中开启),调度依次考虑每个作业,选择符合两个条件的job:[1] 作业所在的用户未达到资源使用上限 [2] 该TaskTracker所在的节点剩余的内存足够该job的task使用。(3) 选择task,同大部分调度器一样,考虑task的locality和资源使用情况。(即:调用JobInProgress中的obtainNewMapTask()/obtainNewReduceTask()方法)综合上述,公平调度器的伪代码为:
  
  
   
   
    
    
     
     
      
      
     
     
     
     // CapacityTaskScheduler:trackTracker出现空闲slot,为slot寻找合适的task
 
List<Task> assignTasks(TaskTrackerStatus taskTracker) {
 
  sortQueuesByResourcesUsesage(queues);
 
  for queue:queues {
 
    sortJobsByTimeAndPriority(queue);
 
    for job:queue.getJobs() {
 
      if(matchesMemoryRequirements(job,taskTracker)) {
 
        task = job. obtainNewTask();
 
        if(task != null) return task
 
      }
 
    }
 
  }
 
}
     
     
      
      
     
     
    
    
    
     
   
   
  
  4. 计算能力调度器源代码分析计算能力调度器位于代码包的hadoop-0.20.2\src\contrib\capacity-scheduler目录下。4.1 源代码包组成(共5个java文件)CapacitySchedulerConf.java:管理配置文件CapacityTaskScheduler.java:调度器的核心代码JobQueuesManager.java:管理作业队列MemoryMatcher.java:用于判断job与内存容量是否匹配JobInitializationPoller.java:作业初始化类,用户可同时启动多个线程,加快作业初始化速度。4.2 CapacityTaskScheduler分析只介绍调度器最核心的代码,即CapacityTaskScheduler.java文件中的代码。(1) 几个基本的内类:[1] TaskSchedulingInfo(TSI):用以维护某种task(MAP或者REDUCE)的调度信息,包括numRunningTasks,numSlotsOccupied等[2] QueueSchedulingInfo(QSI):用以跟踪某个queue中的调度信息,包括capacityPercent,ulMin等[3] TaskSchedulingMgr:调度的核心实现算法,这是一个抽象类,有两个派生类,分别为:MapSchedulingMgr和ReduceSchedulingMgr,用以实现map task和reduce task的调度策略(2) 核心方法(按照执行顺序分析):[1] CapacityTaskScheduler.start(): 调度器初始化,包括加载配置文件,初始化各种对象和变量等。[2] CapacityTaskScheduler. assignTasks ():当有一个TaskTracker的HeartBeat到达JobTracker时,如果有空闲的slot,JobTracker会调用Capacity Scheduler中的assignTasks方法,该方法会为该TaskTracker需找若干个合适的task。在assignTasks方法中,会调用TaskSchedulingMgr中的方法。前面提到TaskSchedulingMgr是一个抽象类,它实现了所有派生类必须使用的方法:[3] TaskSchedulingMgr.assignTasks (taskTracker):对外提供的最直接的调用函数,主要作用是为taskTracker选择一个合适的task,该函数会依次扫描系统中所有的queue(queue已经被排好序,排序类为TaskSchedulingMgr.QueueComparator),对于每个queue,调用getTaskFromQueue(taskTracker, qsi)。[4] TaskSchedulingMgr.getTaskFromQueue(taskTracker, qsi):从队列qsi中选择一个符合条件的作业,这里的“条件”包括用户的资源量上限,taskTracker空闲内存等。5. 计算能力调度器与公平调度器对比(1) 相同点@ 均支持多用户多队列,即:适用于多用户共享集群的应用环境@ 单个队列均支持优先级和FIFO调度方式@ 均支持资源共享,即某个queue中的资源有剩余时,可共享给其他缺资源的queue(2) 不同点@ 核心调度策略不同。 计算能力调度器的调度策略是,先选择资源利用率低的queue,然后在queue中同时考虑FIFO和memory constraint因素;而公平调度器仅考虑公平,而公平是通过作业缺额体现的,调度器每次选择缺额最大的job(queue的资源量,job优先级等仅用于计算作业缺额)。@ 内存约束。计算能力调度器调度job时会考虑作业的内存限制,为了满足某些特殊job的特殊内存需求,可能会为该job分配多个slot;而公平调度器对这种特殊的job无能为力,只能杀掉这种task。6. 参考资料(1) http://hadoop.apache.org/common/docs/r0.20.2/capacity_scheduler.html(2) Hadoop 0.20.2 源代码



hadoop默认的late算法 hadoop默认调度_ci


这里配置了三个队列,分别是hive,pig,default,hive的容量是40%,由属性mapred.capacity-scheduler.queue.hive.capacity决定,其他队列的容量同理可得。

需要配置hive,pig,default可以抢占整个集群的资源,由属性mapred.capacity-scheduler.queue.hive.user-limit-factor绝对,hive队列这个值是3,所以用户可以使用的资源限量是40% * 3 =120%,所有有效计算容量是集群的100%.其他队列的最大集群计算容量同理可得。

 

如何使用该队列

mapreduce:在Job的代码中,设置Job属于的队列,例如hive:


conf.setQueueName("hive");


hive:在执行hive任务时,设置hive属于的队列,例如pig:


set mapred.job.queue.name=pig;


 

动态更新集群队列和容量

生产环境中,队列及其容量的修改在现实中是不可避免的,而每次修改,需要重启集群,这个代价很高,如果修改队列及其容量的配置不重启呢:

1.在主节点上根据具体需求,修改好mapred-site.xml和capacity-scheduler.xml

2.把配置同步到所有节点上

3.使用hadoop用户执行命令:hadoop mradmin -refreshQueues

这样就可以动态修改集群的队列及其容量配置,不需要重启了,刷新mapreduce的web管理控制台可以看到结果。

注意:如果配置没有同步到所有的节点,一些队列会无法启用。