1. 程式人生 > >Yarn下Mapreduce的記憶體引數理解&xml引數配置

Yarn下Mapreduce的記憶體引數理解&xml引數配置

Container是什麼?

Container就是一個yarn的java程序,在Mapreduce中的AM,MapTask,ReduceTask都作為Container在Yarn的框架上執行,你可以在RM的網頁上【8088埠】看到Container的狀態

基礎

Yarn的ResourceManger(簡稱RM)通過邏輯上的佇列分配記憶體,CPU等資源給application,預設情況下RM允許最大AM申請Container資源為8192MB(“yarn.scheduler.maximum-allocation-mb“),預設情況下的最小分配資源為1024M(“yarn.scheduler.minimum-allocation-mb“),AM只能以增量(”yarn.scheduler.minimum-allocation-mb“)和不會超過(“yarn.scheduler.maximum-allocation-mb“)的值去向RM申請資源,AM負責將(“mapreduce.map.memory.mb“)和(“mapreduce.reduce.memory.mb“)的值規整到能被(“yarn.scheduler.minimum-allocation-mb“)整除,RM會拒絕申請記憶體超過8192MB和不能被1024MB整除的資源請求【記憶體增量】。

本文基於Hadoop2.6;下面提到的配置項最好都要設定以覆蓋預設值,以便調優。

1、yarn-site.xml 設定

yarn進行資源管理的時候:以contain作為最小單位來進行資源分配的。
事實上Hadoop所有設定都可以寫在同一個xml中,但是為了自己檢視方便,模組化,所以分開寫。
yarn-site.xml主要設定yarn的基本配置,以yarn開頭的配置項。修改後必須重啟叢集生效。
mapred-site.xml主要設定mapreduxe任務的配置項;這個檔案修改後不需重啟叢集。

1.1 NM設定(NodeManager)

NM的記憶體資源配置,主要是通過下面兩個引數進行的(這兩個值是Yarn平臺特性,應在yarn-sit.xml中配置) :
yarn.nodemanager.resource.memory-mb 預設8GB
yarn.nodemanager.vmem-pmem-ratio 預設2.1
說明:第一個引數:該結點向作業系統申請的記憶體總量,RM中的兩個值不能超過此值。此數值可以用於計算container最大數目,即:用此值除以RM中的最小容器記憶體。第二個:虛擬記憶體率,是佔task所用記憶體的百分比,預設值為2.1倍。如報錯虛擬記憶體溢位,則提高該值。
注意:第一個引數預設大小是8G,即使計算機記憶體不足8G也會按著8G記憶體來使用,所有計算機記憶體小於8GB應該調低這個值。

1.2 RM設定(ResourceManager)

RM的記憶體資源配置,主要是通過下面的兩個引數進行的(這兩個值是Yarn平臺特性,應在yarn-sit.xml中配置):
yarn.scheduler.minimum-allocation-mb 預設1GB
yarn.scheduler.maximum-allocation-mb 預設8GB
說明:單個容器可申請的最小與最大記憶體,應用在執行申請記憶體時不能超過最大值,應用申請小於最小值則會分配最小值,從這個角度看,最小值有點像作業系統中的頁。最小值還有另外一種用途,用來計算一個節點的最大container數目。注:這兩個值一經設定不能動態改變(此處所說的動態改變是指需要重啟叢集生效)。

2、mapred-site.xml 設定見文後附錄

2.1 AM設定(ApplicationManager)

AM記憶體配置相關引數,此處以MapReduce為例進行說明(這兩個值是AM特性,應在mapred-site.xml中配置),如下:
mapreduce.map.memory.mb 預設
mapreduce.reduce.memory.mb 預設
說明:單個Map/Reduce task 申請的記憶體大小,其值應該在RM中的最大和最小container值之間。如果沒有配置則通過如下簡單公式獲得:
max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
一般reduce記憶體大小應該是map的2倍。注:這兩個值可以在應用啟動時通過引數改變,可以動態調整;

2.2 AM JVM設定

AM中其它與記憶體相關的引數,還有JVM相關的引數,這些引數可以通過,如下選項配置:
mapreduce.map.java.opts 預設
mapreduce.reduce.java.opts 預設
說明:這兩個參主要是為需要執行JVM程式(java、scala等)準備的,通過這兩個設定可以向JVM中傳遞引數的,與記憶體有關的是,-Xmx,-Xms等選項。此數值大小,應該在AM中的map.mb和reduce.mb之間。

2.3總結

AM為Map/Reduce task向RM申請資源,RM按照mini和max、資源增量的值為task分配一個固定大小的container供task使用。RM可以分配下去的資源總量受到NM配置的值限制。

3、注意:

在hadoop2及以上版本中,map和reduce task 是執行在container中的。mapreduce.{map|reduce}.memory.mb 被yarn用來設定container的記憶體大小。如果container的記憶體超限,會被yarn殺死。在container中,為了執行map和reduce task,yarn會在contaner中啟動一個jvm來執行task任務。mapreduce.{map|reduce}.java.opts用來設定container啟動的jvm相關引數,通過設定Xmx來設定map 或者reduce task的最大堆記憶體。
理論上,{map|reduce}.java.opts設定的最大堆記憶體要比{map|reduce}.memory.mb小。一般設定為一般設定為0.75倍的memory.mb即可;因為在yarn container這種模式下,JVM程序跑在container中,需要為java code等非JVM的記憶體使用預留些空間。
執行中的設定方法例如:xml中也可設定
hadoop jar -Dmapreduce.reduce.memory.mb=4096 -Dmapreduce.map.java.opts=-Xmx3276

4、常見記憶體溢位報錯&解決

預設情況下,yarn.nodemanager.vmem-pmem-ratio被設定為2.1,這意味著,每個map或者task任務只能使用2.1倍(”mapreduce.reduce.memory.mb”) or (“mapreduce.map.memory.mb”) 大小的虛擬記憶體,如果使用的量超出則會被nm殺掉。
例如:日誌中常見報錯:
1、Container xxx is running beyond physical memory limits
2、java heap space
3、Error: GC overhead limit exceeded

報錯1:Current usage: 1.1gb of 2.0gb physical memory used; 4.6gb of 4.2gb virtual memory used. Killing container.【即虛擬記憶體溢位】;
**方法一:提高yarn.nodemanager.vmem-pmem-ratio = 5或者更高;【推薦】**
方法二:yarn.nodemanager.vmem-check-enabled =false ;關閉虛擬記憶體檢查;不推薦
方法三:提高實體記憶體分配,相應的虛擬記憶體自然就多了,但是這樣不是最優
報錯2:Current usage: 2.1gb of 2.0gb physical memory used; 3.6gb of 4.2gb virtual memory used. Killing container.【即實體記憶體溢位】;
方法一:mapreduce.map.memory.mb = 3GB以上,然後測試這個map/reduce task需要使用多少記憶體才夠用,提高這個值直到不報錯為止。
方法二:提高yarn.scheduler.minimum-allocation-mb = 3GB以上,同理【不推薦】

5、記憶體分配增量/規整因子/incrementMemory

為了易於管理資源和排程資源,Hadoop YARN內建了資源規整化演算法,它規定了最小可申請資源量、最大可申請資源量和資源規整化因子,規整化因子是用來規整化應用程式資源的,應用程式申請的資源如果不是該因子的整數倍,則將被修改為最小的整數倍對應的值,公式為ceil(a/b)*b,其中a是應用程式申請的資源,b為規整化因子。對於規整化因子,不同調度器不同,具體如下:
FIFO和Capacity Scheduler,規整化因子等於最小可申請資源量,不可單獨配置。
Fair Scheduler:規整化因子通過引數yarn.scheduler.increment-allocation-mb和yarn.scheduler.increment-allocation-vcores設定,預設是1024和1。
通過以上介紹可知,應用程式申請到資源量可能大於資源申請的資源量,比如YARN的最小可申請資源記憶體量為1024,規整因子是1024,如果一個應用程式申請1500記憶體,則會得到2048記憶體,如果規整因子是512,則得到1536記憶體。

如下圖:map container的記憶體(“mapreduce.map.memory.mb”)被設定為1536mb 。但是AM會為其申請了2048m的記憶體,因為am的最小分配單位/增量(yarn.scheduler.minimum-allocation-mb)被設定為1024,也就是以1GB為單位往上加。這是一種邏輯上的分配,這個值被NodeManager用來監控該程序記憶體資源的使用率,如果mapTask的堆記憶體使用率超過了2048MB,NM將會把這個task給殺掉。

這裡寫圖片描述
從上面的圖可以看出map,reduce,AM container的JVM,“JVM”矩形代表服務程序,“Max heap”,“Max virtual”矩形代表NodeManager對JVM程序的最大記憶體和虛擬記憶體的限制。

When a mapreduce job completes you will see several counters dumped at the end of the job.The three memory counters below show how much physical memory was allocated vs virtual memory.

對於56G記憶體的NM來說,如果全部跑map則56/3大約跑18個container
大概瞭解完以上的引數之後,mapreduce.map.java.opts和mapreduce.map.memory.mb引數之間,有什麼聯絡呢?
通過上面的分析,我們知道如果一個yarn的container超除了heap設定的大小,這個task將會失敗,我們可以根據哪種型別的container失敗去相應增大mapreduce.{map|reduce}.memory.mb去解決問題。 但同時帶來的問題是叢集並行跑的container的數量少了所以適當的調整記憶體引數對叢集的利用率的提升尤為重要。

對cpu的設定引數:

在yarn的框架中,CPU的配置決定了一個任務的生死,CPU只是決定了任務的完成效率。所以CPU的設定只是簡單列出來。
yarn.scheduler.minimum-allocation-vcores:最小可申請CPU數,預設是1
yarn.scheduler.maximum-allocation-vcores:最大可申請CPU數,預設是4
yarn.nodemanager.resource.cpu-vcores:叢集向系統申請的總可用CPU數目,預設是8

mapreduce.map.cpu.vcores:task container申請的CPU數目,預設是1
完結!

附錄1-我的yarn-site.xml配置:

<?xml version="1.0"?>
<configuration>
<!-- Site specific YARN configuration properties
下面的配置項中值的大小,特別是記憶體大小,通過每個節點logs中的yarn-hadoop-nodemanager-Slave1.log 檔案中檢視日誌來判斷;出錯行形如:
running beyond virtual memory limits. Current usage: 484.0 MB of 2 GB physical memory used; 4.9 GB of 4.2 GB virtual memory used. Killing container.
在yarn-hadoop-resourcemanager-Slave1.log日誌檔案中:形如:表示記憶體和cpu資源分配:
例如:總的結點資源:<memory:16000, vCores:8>==<memory:10240, vCores:5>+<memory:5760, vCores:3> 
Released container container_1511512572160_0003_01_000025 of capacity <memory:2048, vCores:1> on host Slave1:42899, which currently has 5 containers, <memory:10240, vCores:5> used and <memory:5760, vCores:3> available,
 -->
        <property>
                <name>yarn.resourcemanager.hostname</name>
                <value>Slave1</value>
        </property>
        <property>
                <name>yarn.nodemanager.aux-services</name>
                <value>mapreduce_shuffle</value>
        </property>
        <property>
                <name>yarn.nodemanager.pmem-check-enabled</name>
                <value>true</value>
                <description>檢測實體記憶體的使用是否超出分配值,若任務超出分配值,則將其殺掉,預設true。</description> 
        </property>          
        <property>
                <name>yarn.nodemanager.vmem-check-enabled</name>
                <value>true</value>
                <description>檢測虛擬記憶體的使用是否超出;若任務超出分配值,則將其殺掉,預設true。在確定記憶體不會洩漏的情況下可以設定此項為 False;</description> 
        </property>  
        <property>
                <name>yarn.nodemanager.vmem-pmem-ratio</name>
                <value>8</value>
                <description>任務每使用1MB實體記憶體,最多可使用虛擬記憶體量比率,預設2.1;在上一項中設定為false不檢測虛擬記憶體時,此項就無意義了</description> 
        </property>  
        <property>
                <name>yarn.nodemanager.resource.cpu-vcores</name>
                <value>12</value>
                <description>該節點上YARN可使用的總核心數;一般設為cat /proc/cpuinfo| grep "processor"| wc -l 的值。預設是8個;</description>  
        </property>
        <property>
                <name>yarn.nodemanager.resource.memory-mb</name>
                <value>16000</value>
                <description>該節點上YARN可使用的實體記憶體總量,【向作業系統申請的總量】預設是8192(MB)</description>  
        </property>
        <property>
                <name>yarn.scheduler.minimum-allocation-mb</name>
                <value>3072</value>
                <description>單個容器/排程器可申請的最少實體記憶體量,預設是1024(MB);一般每個contain都分配這個值;即:capacity memory:3072, vCores:1,如果提示實體記憶體溢位,提高這個值即可;</description> 
        </property>
        <property>
                <name>yarn.scheduler.maximum-allocation-mb</name>
                <value>8000</value>
                <description>單個容器申請最大值</description> 
        </property>    

    <property>
    <description>The minimum allocation for every container request at the RM,
    in terms of virtual CPU cores. Requests lower than this will throw a
    InvalidResourceRequestException.</description>
    <name>yarn.scheduler.minimum-allocation-vcores</name>
    <value>1</value>
  </property>

<property>  
<description>The http address of the RM web application.</description>  
<name>yarn.resourcemanager.webapp.address</name>  
<value>${yarn.resourcemanager.hostname}:8088</value>  
</property>  

</configuration>

附錄2-我的mapred-site.xml:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file.
 -->
<configuration>
        <property>
                <name>mapreduce.framework.name</name>
                <value>yarn</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.address</name>
                <value>Slave1:10020</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.webapp.address</name>
                <value>Slave1:19888</value>
        </property>

        <property>
                <name>mapreduce.map.cpu.vcores</name>
                <value>2</value>
                <description>每個MapTask容器申請的核心數;預設1</description> 
        </property>   
        <property>
                <name>mapreduce.map.memory.mb</name>
                <value>4096</value>
                <description>每個Map task容器申請的記憶體大小;預設1G</description> 
        </property>
        <property>
                <name>mapreduce.map.java.opts</name>
                <value>-Xmx3072m</value>
                <description>map使用的JVM的堆大小heapsize;根據單個mapper/reducer容器記憶體進行調整,heapsize不能大於單個mapper/reducer容器記憶體值,一般設定為mapreduce.map.memory.mb的85%左右</description> 
        </property>  
<!--reduce階段的設定 -->
        <property>
                <name>mapreduce.reduce.cpu.vcores</name>
                <value>2</value>
                <description>每個ReduceTask容器申請的核心數;預設1</description> 
        </property> 
        <property>
                <name>mapreduce.reduce.memory.mb</name>
                <value>8192</value>
                <description>Reduce task申請的記憶體大小</description> 
        </property>             
        <property>
                <name>mapreduce.reduce.java.opts</name>
                <value>-Xmx6144m</value>
                <description>Reduce階段的JVM的堆大小;同上</description> 
        </property>
</configuration>