YARN的Memory和CPU調優配置詳解 轉

Hadoop YARN同時支持內存和CPU兩種資源的調度,本文介紹如何配置YARN對內存和CPU的使用。

YARN作爲一個資源調度器,應該考慮到集羣裏面每一臺機子的計算資源,然後根據application申請的資源進行分配Container。Container是YARN裏面資源分配的基本單位,具有一定的內存以及CPU資源。

在YARN集羣中,平衡內存、CPU、磁盤的資源的很重要的,根據經驗,每兩個container使用一塊磁盤以及一個CPU核的時候可以使集羣的資源得到一個比較好的利用。

內存配置

關於內存相關的配置可以參考hortonwork公司的文檔Determine HDP Memory Configuration Settings來配置你的集羣。

YARN以及MAPREDUCE所有可用的內存資源應該要除去系統運行需要的以及其他的hadoop的一些程序,總共保留的內存=系統內存+HBASE內存。

可以參考下面的表格確定應該保留的內存:

每臺機子內存 系統需要的內存 HBase需要的內存
4GB 1GB 1GB
8GB 2GB 1GB
16GB 2GB 2GB
24GB 4GB 4GB
48GB 6GB 8GB
64GB 8GB 8GB
72GB 8GB 8GB
96GB 12GB 16GB
128GB 24GB 24GB
255GB 32GB 32GB
512GB 64GB 64GB

計算每臺機子最多可以擁有多少個container,可以使用下面的公式:

containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)

說明:

  • CORES爲機器CPU核數
  • DISKS爲機器上掛載的磁盤個數
  • Total available RAM爲機器總內存
  • MIN_CONTAINER_SIZE是指container最小的容量大小,這需要根據具體情況去設置,可以參考下面的表格:
每臺機子可用的RAM container最小值
小於4GB 256MB
4GB到8GB之間 512MB
8GB到24GB之間 1024MB
大於24GB 2048MB

每個container的平均使用內存大小計算方式爲:

RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))

通過上面的計算,YARN以及MAPREDUCE可以這樣配置:

配置文件 配置設置 默認值 計算值
yarn-site.xml yarn.nodemanager.resource.memory-mb 8192 MB = containers * RAM-per-container
yarn-site.xml yarn.scheduler.minimum-allocation-mb 1024MB = RAM-per-container
yarn-site.xml yarn.scheduler.maximum-allocation-mb 8192 MB = containers * RAM-per-container
yarn-site.xml (check) yarn.app.mapreduce.am.resource.mb 1536 MB = 2 * RAM-per-container
yarn-site.xml (check) yarn.app.mapreduce.am.command-opts -Xmx1024m = 0.8 * 2 * RAM-per-container
mapred-site.xml mapreduce.map.memory.mb 1024 MB = RAM-per-container
mapred-site.xml mapreduce.reduce.memory.mb 1024 MB = 2 * RAM-per-container
mapred-site.xml mapreduce.map.java.opts   = 0.8 * RAM-per-container
mapred-site.xml mapreduce.reduce.java.opts   = 0.8 * 2 * RAM-per-container

舉個例子:對於128G內存、32核CPU的機器,掛載了7個磁盤,根據上面的說明,系統保留內存爲24G,不適應HBase情況下,系統剩餘可用內存爲104G,計算containers值如下:

containers = min (2*32, 1.8* 7 , (128-24)/2) = min (64, 12.6 , 51) = 13

計算RAM-per-container值如下:

RAM-per-container = max (2, (124-24)/13) = max (2, 8) = 8

你也可以使用腳本yarn-utils.py來計算上面的值:

點擊(此處)摺疊或打開

  1. #!/usr/bin/env python
  2. import optparse
  3. from pprint import pprint
  4. import logging
  5. import sys
  6. import math
  7. import ast
  8.  
  9. ''' Reserved for OS + DN + NM, Map: Memory => Reservation '''
  10. reservedStack = { 4:1, 8:2, 16:2, 24:4, 48:6, 64:8, 72:8, 96:12, 
  11.                    128:24, 256:32, 512:64}
  12. ''' Reserved for HBase. Map: Memory => Reservation '''
  13.   
  14. reservedHBase = {4:1, 8:1, 16:2, 24:4, 48:8, 64:8, 72:8, 96:16, 
  15.                    128:24, 256:32, 512:64}
  16. GB = 1024
  17.  
  18. def getMinContainerSize(memory):
  19.   if (memory <= 4):
  20.     return 256
  21.   elif (memory <= 8):
  22.     return 512
  23.   elif (memory <= 24):
  24.     return 1024
  25.   else:
  26.     return 2048
  27.   pass
  28.  
  29. def getReservedStackMemory(memory):
  30.   if (reservedStack.has_key(memory)):
  31.     return reservedStack[memory]
  32.   if (memory <= 4):
  33.     ret = 1
  34.   elif (memory >= 512):
  35.     ret = 64
  36.   else:
  37.     ret = 1
  38.   return ret
  39.  
  40. def getReservedHBaseMem(memory):
  41.   if (reservedHBase.has_key(memory)):
  42.     return reservedHBase[memory]
  43.   if (memory <= 4):
  44.     ret = 1
  45.   elif (memory >= 512):
  46.     ret = 64
  47.   else:
  48.     ret = 2
  49.   return ret
  50.                     
  51. def main():
  52.   log = logging.getLogger(__name__)
  53.   out_hdlr = logging.StreamHandler(sys.stdout)
  54.   out_hdlr.setFormatter(logging.Formatter(' %(message)s'))
  55.   out_hdlr.setLevel(logging.INFO)
  56.   log.addHandler(out_hdlr)
  57.   log.setLevel(logging.INFO)
  58.   parser = optparse.OptionParser()
  59.   memory = 0
  60.   cores = 0
  61.   disks = 0
  62.   hbaseEnabled = True
  63.   parser.add_option('-c', '--cores', default = 16,
  64.                      help = 'Number of cores on each host')
  65.   parser.add_option('-m', '--memory', default = 64, 
  66.                     help = 'Amount of Memory on each host in GB')
  67.   parser.add_option('-d', '--disks', default = 4, 
  68.                     help = 'Number of disks on each host')
  69.   parser.add_option('-k', '--hbase', default = "True",
  70.                     help = 'True if HBase is installed, False is not')
  71.   (options, args) = parser.parse_args()
  72.   
  73.   cores = int (options.cores)
  74.   memory = int (options.memory)
  75.   disks = int (options.disks)
  76.   hbaseEnabled = ast.literal_eval(options.hbase)
  77.   
  78.   log.info("Using cores=" + str(cores) + " memory=" + str(memory) + "GB" +
  79.             " disks=" + str(disks) + " hbase=" + str(hbaseEnabled))
  80.   minContainerSize = getMinContainerSize(memory)
  81.   reservedStackMemory = getReservedStackMemory(memory)
  82.   reservedHBaseMemory = 0
  83.   if (hbaseEnabled):
  84.     reservedHBaseMemory = getReservedHBaseMem(memory)
  85.   reservedMem = reservedStackMemory + reservedHBaseMemory
  86.   usableMem = memory - reservedMem
  87.   memory -= (reservedMem)
  88.   if (memory < 2):
  89.     memory = 2
  90.     reservedMem = max(0, memory - reservedMem)
  91.     
  92.   memory *= GB
  93.   
  94.   containers = int (min(2 * cores,
  95.                          min(math.ceil(1.8 * float(disks)),
  96.                               memory/minContainerSize)))
  97.   if (containers <= 2):
  98.     containers = 3
  99.  
  100.   log.info("Profile: cores=" + str(cores) + " memory=" + str(memory) + "MB"
  101.            + " reserved=" + str(reservedMem) + "GB" + " usableMem="
  102.            + str(usableMem) + "GB" + " disks=" + str(disks))
  103.     
  104.   container_ram = abs(memory/containers)
  105.   if (container_ram > GB):
  106.     container_ram = int(math.floor(container_ram / 512)) * 512
  107.   log.info("Num Container=" + str(containers))
  108.   log.info("Container Ram=" + str(container_ram) + "MB")
  109.   log.info("Used Ram=" + str(int (containers*container_ram/float(GB))) + "GB")
  110.   log.info("Unused Ram=" + str(reservedMem) + "GB")
  111.   log.info("yarn.scheduler.minimum-allocation-mb=" + str(container_ram))
  112.   log.info("yarn.scheduler.maximum-allocation-mb=" + str(containers*container_ram))
  113.   log.info("yarn.nodemanager.resource.memory-mb=" + str(containers*container_ram))
  114.   map_memory = container_ram
  115.   reduce_memory = 2*container_ram if (container_ram <= 2048) else container_ram
  116.   am_memory = max(map_memory, reduce_memory)
  117.   log.info("mapreduce.map.memory.mb=" + str(map_memory))
  118.   log.info("mapreduce.map.java.opts=-Xmx" + str(int(0.8 * map_memory)) +"m")
  119.   log.info("mapreduce.reduce.memory.mb=" + str(reduce_memory))
  120.   log.info("mapreduce.reduce.java.opts=-Xmx" + str(int(0.8 * reduce_memory)) + "m")
  121.   log.info("yarn.app.mapreduce.am.resource.mb=" + str(am_memory))
  122.   log.info("yarn.app.mapreduce.am.command-opts=-Xmx" + str(int(0.8*am_memory)) + "m")
  123.   log.info("mapreduce.task.io.sort.mb=" + str(int(0.4 * map_memory)))
  124.   pass
  125.  
  126. if __name__ == '__main__':
  127.   try:
  128.     main()
  129.   except(KeyboardInterrupt, EOFError):
  130.     print("\nAborting ... Keyboard Interrupt.")
  131.     sys.exit(1)

 

執行下面命令:

python yarn-utils.py -c 32 -m 128 -d 7 -k False

 

返回結果如下:

點擊(此處)摺疊或打開

  1. Using cores=32 memory=128GB disks=7 hbase=False
  2.  Profile: cores=32 memory=106496MB reserved=24GB usableMem=104GB disks=7
  3.  Num Container=13
  4.  Container Ram=8192MB
  5.  Used Ram=104GB
  6.  Unused Ram=24GB
  7.  yarn.scheduler.minimum-allocation-mb=8192
  8.  yarn.scheduler.maximum-allocation-mb=106496
  9.  yarn.nodemanager.resource.memory-mb=106496
  10.  mapreduce.map.memory.mb=8192
  11.  mapreduce.map.java.opts=-Xmx6553m
  12.  mapreduce.reduce.memory.mb=8192
  13.  mapreduce.reduce.java.opts=-Xmx6553m
  14.  yarn.app.mapreduce.am.resource.mb=8192
  15.  yarn.app.mapreduce.am.command-opts=-Xmx6553m
  16.  mapreduce.task.io.sort.mb=3276

 

 

這樣的話,每個container內存爲8G,似乎有點多,我更願意根據集羣使用情況任務將其調整爲2G內存,則集羣中下面的參數配置值如下:

配置文件 配置設置 計算值
yarn-site.xml yarn.nodemanager.resource.memory-mb = 52 * 2 =104 G
yarn-site.xml yarn.scheduler.minimum-allocation-mb = 2G
yarn-site.xml yarn.scheduler.maximum-allocation-mb = 52 * 2 = 104G
yarn-site.xml (check) yarn.app.mapreduce.am.resource.mb = 2 * 2=4G
yarn-site.xml (check) yarn.app.mapreduce.am.command-opts = 0.8 * 2 * 2=3.2G
mapred-site.xml mapreduce.map.memory.mb = 2G
mapred-site.xml mapreduce.reduce.memory.mb = 2 * 2=4G
mapred-site.xml mapreduce.map.java.opts = 0.8 * 2=1.6G
mapred-site.xml mapreduce.reduce.java.opts = 0.8 * 2 * 2=3.2G

對應的xml配置爲:

點擊(此處)摺疊或打開

  1. <property>
  2.       <name>yarn.nodemanager.resource.memory-mb</name>
  3.       <value>106496</value>
  4.   </property>
  5.   <property>
  6.       <name>yarn.scheduler.minimum-allocation-mb</name>
  7.       <value>2048</value>
  8.   </property>
  9.   <property>
  10.       <name>yarn.scheduler.maximum-allocation-mb</name>
  11.       <value>106496</value>
  12.   </property>
  13.   <property>
  14.       <name>yarn.app.mapreduce.am.resource.mb</name>
  15.       <value>4096</value>
  16.   </property>
  17.   <property>
  18.       <name>yarn.app.mapreduce.am.command-opts</name>
  19.       <value>-Xmx3276m</value>
  20.   </property>

另外,還有一下幾個參數:

  • yarn.nodemanager.vmem-pmem-ratio:任務每使用1MB物理內存,最多可使用虛擬內存量,默認是2.1。
  • yarn.nodemanager.pmem-check-enabled:是否啓動一個線程檢查每個任務正使用的物理內存量,如果任務超出分配值,則直接將其殺掉,默認是true。
  • yarn.nodemanager.vmem-pmem-ratio:是否啓動一個線程檢查每個任務正使用的虛擬內存量,如果任務超出分配值,則直接將其殺掉,默認是true。

第一個參數的意思是當一個map任務總共分配的物理內存爲2G的時候,該任務的container最多內分配的堆內存爲1.6G,可以分配的虛擬內存上限爲2*2.1=4.2G。另外,照這樣算下去,每個節點上YARN可以啓動的Map數爲104/2=52個。

CPU配置

YARN中目前的CPU被劃分成虛擬CPU(CPU virtual Core),這裏的虛擬CPU是YARN自己引入的概念,初衷是,考慮到不同節點的CPU性能可能不同,每個CPU具有的計算能力也是不一樣的,比如某個物理CPU的計算能力可能是另外一個物理CPU的2倍,這時候,你可以通過爲第一個物理CPU多配置幾個虛擬CPU彌補這種差異。用戶提交作業時,可以指定每個任務需要的虛擬CPU個數。

在YARN中,CPU相關配置參數如下:

  • yarn.nodemanager.resource.cpu-vcores:表示該節點上YARN可使用的虛擬CPU個數,默認是8,注意,目前推薦將該值設值爲與物理CPU核數數目相同。如果你的節點CPU核數不夠8個,則需要調減小這個值,而YARN不會智能的探測節點的物理CPU總數。
  • yarn.scheduler.minimum-allocation-vcores:單個任務可申請的最小虛擬CPU個數,默認是1,如果一個任務申請的CPU個數少於該數,則該對應的值改爲這個數。
  • yarn.scheduler.maximum-allocation-vcores:單個任務可申請的最多虛擬CPU個數,默認是32。

對於一個CPU核數較多的集羣來說,上面的默認配置顯然是不合適的,在我的測試集羣中,4個節點每個機器CPU核數爲31,留一個給操作系統,可以配置爲:

點擊(此處)摺疊或打開

  1. <property>
  2.       <name>yarn.nodemanager.resource.cpu-vcores</name>
  3.       <value>31</value>
  4.   </property>
  5.   <property>
  6.       <name>yarn.scheduler.maximum-allocation-vcores</name>
  7.       <value>124</value>
  8.   </property>

把CDH搭建起來了,跑其中的例子程序word-count。在控制檯界面一直顯示map 0%  reduce 0% , 通過web頁面查看job的狀態一直是run,但是map沒有執行。感覺是是資源的分配有問題。接着查看了任務的日誌。

2014-07-04 17:30:37,492 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Recalculating schedule, headroom=0
2014-07-04 17:30:37,492 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Reduce slow start threshold not met. completedMapsForReduceSlowstart 2
2014-07-04 17:30:38,496 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Ramping down all scheduled reduces:0
2014-07-04 17:30:38,496 INFO [RMCommunicator Allocator] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Going to preempt 0

 

日誌中沒有任何的錯誤,但是一直打印該信息,應該是RM資源分配不夠。

YARN中,資源包括內存和CPU,資源的管理是由ResourceManager和NodeManager共同完成,ResourceManager負責所有節點資源的管理和調度。NodeManager負責進程所在結點資源的分配和隔離。ResourceManager將某個NodeManager上資源分配給任務。下面詳細介紹其中的一些重要參數。

yarn.nodemanager.resource.memory-mb

每個節點可用的內存, 它的單 位是mb,默認是8G,用於供NodeManager分配的。我出現的問題是資源分配太小,只有1G。

yarn.scheduler.minimum-allocation-mb

單個任務可申請的最小內存,默認是1024mb,稍微大一點,避免小的資源浪費情況,我本機資源少,所以給他分配了512mb, 失敗的原因也就是這個分配過大。

yarn.scheduler.maximum-allocation-mb

單個任務可申請的最大內存,默認是8192mb. 如果是spark任務的話,這裏調大吧

mapreduce.map.memory.mb

每個map任務的物理內存限制,應該大於或等於yarn.scheduler.minimum-allocation-mb

mapreduce.reduce.memory.mb

每個reduce任務的物理內存限制

mapreduce.map.java.opts

每個map進程的jvm堆的大小

mapreduce.reduce.java.opts

每個reduce進程的jvm堆的大小

 

每個節點可以運行map數和redue輸,由yarn.nodemanager.resource.memory-mb除於mapreduce.map.memory.mb和mapreduce.reduce.memory.mb得到

yarn資源memory與core計算配置

 

yarn調度分配主要是針對Memory與CPU進行管理分配,並將其組合抽象成container來管理計算使用

 

 

memory配置

  計算每臺機子最多可以擁有多少個container:

     containers = min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE) 

 

   說明:

      CORES爲機器CPU核數

      DISKS爲機器上掛載的磁盤個數

      Total available RAM爲機器總內存
      MIN_CONTAINER_SIZE是指container最小的容量大小,這需要根據具體情況去設置,可以參考下面的表格:

                  

  每個container的平均使用內存大小計算方式爲:

       RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers)) 

 

 相關配置調整說明:

複製代碼

(1)yarn.nodemanager.resource.memory-mb
    表示該節點上YARN可使用的物理內存總量,默認是8192(MB),注意,如果你的節點內存資源不夠8GB,則需要調減小這個值,而YARN不會智能的探測節點的物理內存總量。

(2)yarn.nodemanager.vmem-pmem-ratio
    任務每使用1MB物理內存,最多可使用虛擬內存量,默認是2.1。

(3) yarn.nodemanager.pmem-check-enabled
    是否啓動一個線程檢查每個任務正使用的物理內存量,如果任務超出分配值,則直接將其殺掉,默認是true。

(4) yarn.nodemanager.vmem-check-enabled
    是否啓動一個線程檢查每個任務正使用的虛擬內存量,如果任務超出分配值,則直接將其殺掉,默認是true。

(5)yarn.scheduler.minimum-allocation-mb
    單個container可申請的最少物理內存量,默認是1024(MB),如果一個任務申請的物理內存量少於該值,則該對應的值改爲這個數。

(6)yarn.scheduler.maximum-allocation-mb
    單個container可申請的最多物理內存量,默認是8192(MB)。

複製代碼

  

  默認情況下,YARN採用了線程監控的方法判斷任務是否超量使用內存,一旦發現超量,則直接將其殺死。由於Cgroups對內存的控制缺乏靈活性(即任務任何時刻不能超過內存上限,如果超過,則直接將其殺死或者報OOM),而Java進程在創建瞬間內存將翻倍,之後驟降到正常值,這種情況下,採用線程監控的方式更加靈活(當發現進程樹內存瞬間翻倍超過設定值時,可認爲是正常現象,不會將任務殺死),因此YARN未提供Cgroups內存隔離機制。

 

 

CPU配置

  在yarn中使用的是虛擬CPU,這裏的虛擬CPU是YARN自己引入的概念,初衷是,考慮到不同節點的CPU性能可能不同,每個CPU具有的計算能力也是不一樣的,比如某個物理CPU的計算能力可能是另外一個物理CPU的2倍,這時候,你可以通過爲第一個物理CPU多配置幾個虛擬CPU彌補這種差異。用戶提交作業時,可以指定每個任務需要的虛擬CPU個數。在YARN中,CPU相關配置參數如下:

複製代碼

(1)yarn.nodemanager.resource.cpu-vcores
    表示該節點上YARN可使用的虛擬CPU個數,默認是8,注意,目前推薦將該值設值爲與物理CPU核數數目相同。
    如果你的節點CPU核數不夠8個,則需要調減小這個值,而YARN不會智能的探測節點的物理CPU總數。

(2)yarn.scheduler.minimum-allocation-vcores
    單個任務可申請的最小虛擬CPU個數,默認是1,如果一個任務申請的CPU個數少於該數,則該對應的值改爲這個數。

(3)yarn.scheduler.maximum-allocation-vcores
    單個任務可申請的最多虛擬CPU個數,默認是32。

複製代碼

  默認情況下,YARN是不會對CPU資源進行調度的,你需要配置相應的資源調度器讓你支持,具體參看以下鏈接:

  (1)Hadoop YARN配置參數剖析(4)—Fair Scheduler相關參數

  (2)Hadoop YARN配置參數剖析(5)—Capacity Scheduler相關參數

 

  默認情況下,NodeManager不會對CPU資源進行任何隔離,你可以通過啓用Cgroups讓你支持CPU隔離。

由於CPU資源的獨特性,目前這種CPU分配方式仍然是粗粒度的。舉個例子,很多任務可能是IO密集型的,消耗的CPU資源非常少,如果此時你爲它分配一個CPU,則是一種嚴重浪費,你完全可以讓他與其他幾個任務公用一個CPU,也就是說,我們需要支持更粒度的CPU表達方式。

  借鑑亞馬遜EC2中CPU資源的劃分方式,即提出了CPU最小單位爲EC2 Compute Unit(ECU),一個ECU代表相當於1.0-1.2 GHz 2007 Opteron or 2007 Xeon處理器的處理能力。YARN提出了CPU最小單位YARN Compute Unit(YCU),目前這個數是一個整數,默認是720,由參數yarn.nodemanager.resource.cpu-ycus-per-core設置,表示一個CPU core具備的計算能力(該feature在2.2.0版本中並不存在,可能增加到2.3.0版本中),這樣,用戶提交作業時,直接指定需要的YCU即可,比如指定值爲360,表示用1/2個CPU core,實際表現爲,只使用一個CPU core的1/2計算時間。注意,在操作系統層,CPU資源是按照時間片分配的,你可以說,一個進程使用1/3的CPU時間片,或者1/5的時間片。對於CPU資源劃分和調度的探討,可參考以下幾個鏈接:

https://issues.apache.org/jira/browse/YARN-1089

https://issues.apache.org/jira/browse/YARN-1024

Hadoop 新特性、改進、優化和Bug分析系列5:YARN-3

本文彙總了幾個hadoop yarn中常見問題以及解決方案,注意,本文介紹解決方案適用於hadoop 2.2.0以及以上版本。

 

(1) 默認情況下,各個節點的負載不均衡(任務數目不同),有的節點很多任務在跑,有的沒有任務,怎樣讓各個節點任務數目儘可能均衡呢?

答: 默認情況下,資源調度器處於批調度模式下,即一個心跳會儘可能多的分配任務,這樣,優先發送心跳過來的節點將會把任務領光(前提:任務數目遠小於集羣可以同時運行的任務數量),爲了避免該情況發生,可以按照以下說明配置參數:

如果採用的是fair scheduler,可在yarn-site.xml中,將參數yarn.scheduler.fair.max.assign設置爲1(默認是-1,)

如果採用的是capacity scheduler(默認調度器),則不能配置,目前該調度器不帶負載均衡之類的功能。

當然,從hadoop集羣利用率角度看,該問題不算問題,因爲一般情況下,用戶任務數目要遠遠大於集羣的併發處理能力的,也就是說,通常情況下,集羣時刻處於忙碌狀態,沒有節點一直空閒着。

 

(2)某個節點上任務數目太多,資源利用率太高,怎麼控制一個節點上的任務數目?

答:一個節點上運行的任務數目主要由兩個因素決定,一個是NodeManager可使用的資源總量,一個是單個任務的資源需求量,比如一個NodeManager上可用資源爲8 GB內存,8 cpu,單個任務資源需求量爲1 GB內存,1cpu,則該節點最多運行8個任務。

NodeManager上可用資源是由管理員在配置文件yarn-site.xml中配置的,相關參數如下:

yarn.nodemanager.resource.memory-mb:總的可用物理內存量,默認是8096

yarn.nodemanager.resource.cpu-vcores:總的可用CPU數目,默認是8

對於MapReduce而言,每個作業的任務資源量可通過以下參數設置:

mapreduce.map.memory.mb:物理內存量,默認是1024

mapreduce.map.cpu.vcores:CPU數目,默認是1

注:以上這些配置屬性的詳細介紹可參考文章:Hadoop YARN配置參數剖析(1)—RM與NM相關參數

默認情況,各個調度器只會對內存資源進行調度,不會考慮CPU資源,你需要在調度器配置文件中進行相關設置,具體可參考文章:Hadoop YARN配置參數剖析(4)—Fair Scheduler相關參數Hadoop YARN配置參數剖析(5)—Capacity Scheduler相關參數

 

(3)如何設置單個任務佔用的內存量和CPU數目?

答:對於MapReduce而言,每個作業的任務資源量可通過以下參數設置:

mapreduce.map.memory.mb:物理內存量,默認是1024

mapreduce.map.cpu.vcores:CPU數目,默認是1

需要注意的是,默認情況,各個調度器只會對內存資源進行調度,不會考慮CPU資源,你需要在調度器配置文件中進行相關設置。

 

(4) 用戶給任務設置的內存量爲1000MB,爲何最終分配的內存卻是1024MB?

答:爲了易於管理資源和調度資源,Hadoop YARN內置了資源規整化算法,它規定了最小可申請資源量、最大可申請資源量和資源規整化因子,如果應用程序申請的資源量小於最小可申請資源量,則YARN會將其大小改爲最小可申請量,也就是說,應用程序獲得資源不會小於自己申請的資源,但也不一定相等;如果應用程序申請的資源量大於最大可申請資源量,則會拋出異常,無法申請成功;規整化因子是用來規整化應用程序資源的,應用程序申請的資源如果不是該因子的整數倍,則將被修改爲最小的整數倍對應的值,公式爲ceil(a/b)*b,其中a是應用程序申請的資源,b爲規整化因子。

以上介紹的參數需在yarn-site.xml中設置,相關參數如下:

yarn.scheduler.minimum-allocation-mb:最小可申請內存量,默認是1024

yarn.scheduler.minimum-allocation-vcores:最小可申請CPU數,默認是1

yarn.scheduler.maximum-allocation-mb:最大可申請內存量,默認是8096

yarn.scheduler.maximum-allocation-vcores:最大可申請CPU數,默認是4

對於規整化因子,不同調度器不同,具體如下:

FIFO和Capacity Scheduler,規整化因子等於最小可申請資源量,不可單獨配置。

Fair Scheduler:規整化因子通過參數yarn.scheduler.increment-allocation-mb和yarn.scheduler.increment-allocation-vcores設置,默認是1024和1。

通過以上介紹可知,應用程序申請到資源量可能大於資源申請的資源量,比如YARN的最小可申請資源內存量爲1024,規整因子是1024,如果一個應用程序申請1500內存,則會得到2048內存,如果規整因子是512,則得到1536內存。

 

(5)我們使用的是Fairscheduler,配置了多個隊列,當用戶提交一個作業,指定的隊列不存在時,Fair Scheduler會自動創建一個新隊列而不是報錯(比如報錯:隊列XXX不存在),如何避免這種情況發生?

答:在yarn-site.xml中設置yarn.scheduler.fair.allow-undeclared-pools,將它的值配置爲false(默認是true)。

 

(6)使用Hadoop 2.0過程中,遇到了錯誤,怎樣排查錯誤?

答:從hadoop 日誌入手,Hadoop日誌存放位置可參考我這篇文章:Hadoop日誌到底存在哪裏?

  前言:hadoop2.x版本和hadoop1.x版本的一個區別就是:hadoop1.x中負責資源和作業調度的是MapReduce,hadoop2.x版本後,MapReduce只專注於計算,資源和作業的調度由YARN來負責。Container是YARN裏面資源分配的基本單位,具有一定的內存以及CPU資源。我們的應用在工作的時候,需要消耗內存和CPU,故當YARN收到application申請,則會根據application申請的資源,分配Container。

    在YARN的NodeManager節點上,會將機器的CPU和內存的一定值抽離出來,抽離成虛擬的值,然後這些虛擬的值在根據配置組成多個Container,當application提出申請時,就會分配相應的Container資源。關於默認值我們可以查看官網,如下表所示。

參數    默認值
yarn.nodemanager.resource.memory-mb
-1
yarn.nodemanager.resource.cpu-vcores
-1
yarn.scheduler.minimum-allocation-mb
1024MB
yarn.scheduler.maximum-allocation-mb
8192MB
yarn.scheduler.minimum-allocation-vcores
1
yarn.scheduler.maximum-allocation-vcores
4
    內存配置

    yarn.nodemanager.resource.memory-mb默認值爲-1,代表着YARN的NodeManager佔總內存的80%。也就是說加入我們的機器爲64GB內存,出去非YARN進程需要的20%內存,我們大概需要64*0.8≈51GB,在分配的時候,單個任務可以申請的默認最小內存爲1G,任務量大的話可最大提高到8GB。

    在生產場景中,簡單的配置,一般情況下:yarn.nodemanager.resource.memory-mb直接設置成我們需要的值,且要是最大和最小內存需求的整數倍;(一般Container容器中最小內存爲4G,最大內存爲16G)

    假如:64GB的機器內存,我們有51GB的內存可用於NodeManager分配,根據上面的介紹,我們可以直接將yarn.nodemanager.resource.memory-mb值爲48GB,然後容器最小內存爲4GB,最大內存爲16GB,也就是在當前的NodeManager節點下,我們最多可以有12個容器,最少可以有3個容器。

    CPU配置

    此處的CPU指的是虛擬的CPU(CPU virtual core),之所以產生虛擬CPU(CPU vCore)這一概念,是因爲物理CPU的處理能力的差異,爲平衡這種差異,就引入這一概念。

    yarn.nodemanager.resource.cpu-vcores表示能夠分配給Container的CPU核數,默認配置爲-1,代表值爲8個虛擬CPU,推薦該值的設置和物理CPU的核數數量相同,若不夠,則需要調小該值。

    yarn.scheduler.minimum-allocation-vcores的默認值爲1,表示每個Container容器在處理任務的時候可申請的最少CPU個數爲1個。

    yarn.scheduler.maximum-allocation-vcores的默認值爲4,表示每個Container容器在處理任務的時候可申請的最大CPU個數爲4個。

PS:以上內容是小編我學習的理解,以上所示的參數爲配置過程中基本的參數,如果想配置更爲合理,資源利用率更高,可參考小編轉載的兩篇文章,初學者,如有錯誤請指出,謝謝。

YARN和MapReduce的內存配置優化

YARN的memory和CPU配置詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章