Apache Hadoop Day5

caijq_newid發表於2020-10-03

Apache Hadoop Day5

MapReduce Shuffle

定義

MapReduce 中,mapper 階段處理的資料如何傳遞給 reducer 階段,是 MapReduce 框架中 最關鍵的一個流程,這個流程就叫 Shuffle。總體來說shuffle核心流程主要包括以下幾個方面:資料分割槽、排序、區域性聚合/Combiner、緩衝區、溢寫、抓取/Fetch、歸併排序等。
在這裡插入圖片描述

在這裡插入圖片描述

常見問題

1、MapReduce能否實現全域性排序?

預設情況下MapReduce是無法實現全域性有序的,因為底層MapReduce使用的是HashPartitioner實現,僅僅只能保證資料分割槽內部的資料以key的自然順序排列,因此無法實現全域性有序。但是可以有一下思路完成全域性排序:

  • 設定NumReduceTask的個數為1,這樣會導致所有的資料落入到同一個分割槽,即可實現全排序,但是隻適用於小批量資料集
  • 自定義分割槽策略讓資料按照區間分割槽,不按照hash策略,此時只需要保證區間之間有序即可實現全域性有序。但是這種做法會出現區間資料分佈不均勻,導致計算過程中出現資料傾斜。
  • 使用Hadoop提供的TotalOrderPartitioner,先對目標進行取樣,然後推算出分割槽區間。

參考:https://blog.csdn.net/lalaguozhe/article/details/9211919

2、如何幹預MapReduce的分割槽策略?

一般來說在實際的開發中,很少去幹預分割槽策略,因為基於大資料首先要考慮的是資料的均勻分佈,防止資料傾斜。因此Hash的雜湊往往是最佳的選擇,如果需要覆蓋原有分割槽,可以呼叫:

job.setPartitionerClass(分割槽實現類資訊即可)
public class CustomHashPartitioner<K, V> extends Partitioner<K, V> {

  public int getPartition(K key, V value,
                          int numReduceTasks) {
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }

}

3、如何解決在MapReduce計算過程中的資料傾斜問題(面試熱點問題)?

場景:統計亞洲國家人口,以中國、日本為例。自然會使用國家作為key、公民資訊作為value。在進行MapReduce計算的時候,中國的公民因為國籍都是China自然會落入到一個分割槽中。這樣就出現資料嚴重傾斜。
在這裡插入圖片描述

4、Map、Reduce並行度是靠什麼決定的?

Map端並行度是通過計算任務切片決定的,Reduce端是通過job.setNumReduceTask(n)

5、MapReduce調優策略

1)避免小檔案計算,線下合併成大檔案之後,在進行MapReduce分析或者CombineTextInputFormat。

2)調整環狀緩衝區的引數,減少Map任務的IO操作,不能無限制調大,還要考慮到系統GC問題。

3)開啟Map壓縮,將溢寫檔案壓縮成GZIP格式,減少ReduceShuffle過程中的網路頻寬佔用,消耗CPU為代價

//開啟解壓縮,必須真實的環境下執行
conf.setBoolean("mapreduce.map.output.compress",true);
conf.setClass("mapreduce.map.output.compress.codec", GzipCodec.class, CompressionCodec.class);

4)如果條件允許,我們可以開啟Map端預處理機制,提前在Map端執行Reduce邏輯,進行區域性計算,這樣既可極大提升計算效能,但是這種優化手段並不是所有場景都適合。例如:求均值,這種場景就不適合在Map端執行Reduce邏輯。

1)Combiner/Reduce的輸入和輸出型別必須一致,也就是說預計算邏輯不可以更改Map端輸出型別/Reduce端輸入型別。

2)不可以改變原有的業務邏輯,比如 求平均值,雖然型別相容但是業務計算不正確。
在這裡插入圖片描述

優點:減少Key數量,節省排序所佔用記憶體空間,極大削減了在ReduceShuffle時候的資料下載量,節省頻寬。

5)適當的調整NodeManager管理的資源數

yarn.nodemanager.resource.memory-mb=32G
yarn.nodemanager.resource.cpu-vcores = 16

或者開啟硬體資源監測

yarn.nodemanager.resource.detect-hardware-capabilities=true

6)如果順序執行多個小任務,我們可以考慮使用JVM重用機制,可以使用一個JVM順序執行多個任務,無需重啟新的jvm。

mapreduce.job.jvm.numtasks=2

Hadoop叢集

Hadoop HA構建

概述

NameNode HA構建 儲存、ResourceManager HA構建 計算

在這裡插入圖片描述

準備工作

  • 安裝三臺CentOS作業系統(完成JDK、SSH免密碼認證、IP主機名對映、關閉防火牆等工作)

主機和服務啟動對映表

主機服務
CentOSANameNode、zkfc、DataNode、JournalNode、Zookeeper、NodeManager
CentOSBNameNode、zkfc、DataNode、JournalNode、Zookeeper、NodeManager、ResourceManager
CentOSCDataNode、JournalNode、Zookeeper、NodeManager、ResourceManager

主機資訊

主機名IP資訊
CentOSA192.168.80.142
CentOSB192.168.80.143
CentOSC192.168.80.144

JDK安裝和配置

[root@CentOSX ~]# rpm -ivh jdk-8u171-linux-x64.rpm
[root@CentOSX ~]# vi .bashrc
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.
export JAVA_HOME
export CLASSPATH
export PATH
[root@CentOSX ~]# source .bashrc

IP主機名對映

[root@CentOSX ~]# vi /etc/hosts
192.168.80.142 CentOSA
192.168.80.143 CentOSB
192.168.80.144 CentOSC

關閉防火牆

[root@CentOSX ~]# systemctl stop firewalld
[root@CentOSX ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@CentOSX ~]# firewall-cmd --state
not running

SSH免密碼認證

[root@CentOSX ~]# ssh-keygen -t rsa
[root@CentOSX ~]# ssh-copy-id CentOSA
[root@CentOSX ~]# ssh-copy-id CentOSB
[root@CentOSX ~]# ssh-copy-id CentOSC

Zookeeper

[root@CentOSX ~]# tar -zxf zookeeper-3.4.6.tar.gz -C /usr/
[root@CentOSX ~]# mkdir /root/zkdata

[root@CentOSA ~]# echo 1 >> /root/zkdata/myid
[root@CentOSB ~]# echo 2 >> /root/zkdata/myid
[root@CentOSC ~]# echo 3 >> /root/zkdata/myid

[root@CentOSX ~]# touch /usr/zookeeper-3.4.6/conf/zoo.cfg
[root@CentOSX ~]# vi /usr/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
dataDir=/root/zkdata
clientPort=2181
initLimit=5
syncLimit=2
server.1=CentOSA:2887:3887
server.2=CentOSB:2887:3887
server.3=CentOSC:2887:3887

[root@CentOSX ~]# /usr/zookeeper-3.4.6/bin/zkServer.sh start zoo.cfg
[root@CentOSX ~]# /usr/zookeeper-3.4.6/bin/zkServer.sh status zoo.cfg
JMX enabled by default
Using config: /usr/zookeeper-3.4.6/bin/../conf/zoo.cfg
Mode: `follower|leader`
[root@CentOSX ~]# jps
5879 `QuorumPeerMain`
7423 Jps

搭建Hadoop 叢集(HDFS)

解壓並配置HADOOP_HOME

[root@CentOSX ~]# tar -zxf hadoop-2.9.2.tar.gz -C /usr/
[root@CentOSX ~]# vi .bashrc
HADOOP_HOME=/usr/hadoop-2.9.2
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
CLASSPATH=.
export JAVA_HOME
export CLASSPATH
export PATH
export HADOOP_HOME
[root@CentOSX ~]# source .bashrc

配置core-site.xml

<!--配置Namenode服務ID-->
<property>		
      <name>fs.defaultFS</name>		
      <value>hdfs://mycluster</value>	
</property>
<property>		
     <name>hadoop.tmp.dir</name>		
     <value>/usr/hadoop-2.9.2/hadoop-${user.name}</value>    
</property>
<property>		
     <name>fs.trash.interval</name>		
     <value>30</value>    
</property>
<!--配置機架指令碼-->
<property>		
     <name>net.topology.script.file.name</name>		
     <value>/usr/hadoop-2.9.2/etc/hadoop/rack.sh</value>    
</property>
<!--配置ZK服務資訊-->
<property>   
	<name>ha.zookeeper.quorum</name>
	<value>CentOSA:2181,CentOSB:2181,CentOSC:2181</value> 
</property>
<!--配置SSH祕鑰位置-->
<property>
     <name>dfs.ha.fencing.methods</name>
     <value>sshfence</value>
</property>
<property>
     <name>dfs.ha.fencing.ssh.private-key-files</name>
     <value>/root/.ssh/id_rsa</value>
</property>

配置機架指令碼

[root@CentOSX ~]# touch /usr/hadoop-2.9.2/etc/hadoop/rack.sh
[root@CentOSX ~]# chmod u+x /usr/hadoop-2.9.2/etc/hadoop/rack.sh
[root@CentOSX ~]# vi /usr/hadoop-2.9.2/etc/hadoop/rack.sh
while [ $# -gt 0 ] ; do
	  nodeArg=$1
	  exec</usr/hadoop-2.9.2/etc/hadoop/topology.data
	  result="" 
	  while read line ; do
		ar=( $line ) 
		if [ "${ar[0]}" = "$nodeArg" ] ; then
		  result="${ar[1]}"
		fi
	  done 
	  shift 
	  if [ -z "$result" ] ; then
		echo -n "/default-rack"
	  else
		echo -n "$result "
	  fi
done
[root@CentOSX ~]# touch /usr/hadoop-2.9.2/etc/hadoop/topology.data
[root@CentOSX ~]# vi /usr/hadoop-2.9.2/etc/hadoop/topology.data
192.168.80.142 /rack01
192.168.80.143 /rack01
192.168.80.144 /rack03

配置hdfs-site.xml

<property>
	<name>dfs.replication</name>
	<value>3</value>
</property> 
<!--開啟自動故障轉移-->
<property>
	<name>dfs.ha.automatic-failover.enabled</name>
	<value>true</value>
</property>
<!--解釋core-site.xml內容-->
<property>
	<name>dfs.nameservices</name>
	<value>mycluster</value>
</property>
<property>
	<name>dfs.ha.namenodes.mycluster</name>
	<value>nn1,nn2</value>
</property>
<property>
	<name>dfs.namenode.rpc-address.mycluster.nn1</name>
	<value>CentOSA:9000</value>
</property>
<property>
	 <name>dfs.namenode.rpc-address.mycluster.nn2</name>
	 <value>CentOSB:9000</value>
</property>
<!--配置日誌伺服器的資訊-->
<property>
  <name>dfs.namenode.shared.edits.dir</name>
  <value>qjournal://CentOSA:8485;CentOSB:8485;CentOSC:8485/mycluster</value>
</property>
<!--實現故障轉切換的實現類-->
<property>
	<name>dfs.client.failover.proxy.provider.mycluster</name>
	<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

配置slaves

CentOSA
CentOSB
CentOSC

這裡因為是CentOS7,需要我們額外安裝一個小外掛,psmic否則NameNode無法實現故障自動切換。

[root@CentOSX ~]# yum install -y psmisc 

啟動HDFS(叢集初始化啟動)

[root@CentOSX ~]# hadoop-daemon.sh start journalnode (等待10s鍾)
[root@CentOSA ~]# hdfs namenode -format
[root@CentOSA ~]# hadoop-daemon.sh start namenode
[root@CentOSB ~]# hdfs namenode -bootstrapStandby
[root@CentOSB ~]# hadoop-daemon.sh start namenode
#註冊Namenode資訊到zookeeper中,只需要在CentOSA或者B上任意一臺執行一下指令
[root@CentOSA|B ~]# hdfs zkfc -formatZK
[root@CentOSA ~]# hadoop-daemon.sh start zkfc
[root@CentOSB ~]# hadoop-daemon.sh start zkfc
[root@CentOSX ~]# hadoop-daemon.sh start datanode

檢視機架資訊

[root@CentOSC ~]# hdfs dfsadmin -printTopology
Rack: /rack01
   192.168.73.131:50010 (CentOSA)
   192.168.73.132:50010 (CentOSB)

Rack: /rack03
   192.168.73.133:50010 (CentOSC)

Resource Manager搭建

yarn-site.xml

<property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
</property>
<property>
    <name>yarn.resourcemanager.ha.enabled</name>
    <value>true</value>
</property>
<property>
    <name>yarn.resourcemanager.cluster-id</name>
    <value>cluster</value>
</property>
<property>
    <name>yarn.resourcemanager.ha.rm-ids</name>
    <value>rm1,rm2</value>
</property>
<property>
    <name>yarn.resourcemanager.hostname.rm1</name>
    <value>CentOSB</value>
</property>
<property>
    <name>yarn.resourcemanager.hostname.rm2</name>
    <value>CentOSC</value>
</property>
<property>
    <name>yarn.resourcemanager.zk-address</name>
    <value>CentOSA:2181,CentOSB:2181,CentOSC:2181</value>
</property>
<!--關閉實體記憶體檢查-->
<property>
    <name>yarn.nodemanager.pmem-check-enabled</name>
    <value>false</value>
</property>
<!--關閉虛擬記憶體檢查-->
<property>
    <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
</property>

mapred-site.xml

<property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
</property>

啟動關閉Yarn服務

[root@CentOSB ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSC ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSX ~]# yarn-daemon.sh start|stop nodemanger

如果叢集中某個namenode當機,需要刪除dfs目錄下的name資料夾

false


*mapred-site.xml*

```xml
<property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
</property>

啟動關閉Yarn服務

[root@CentOSB ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSC ~]# yarn-daemon.sh start|stop resourcemanager
[root@CentOSX ~]# yarn-daemon.sh start|stop nodemanger

如果叢集中某個namenode當機,需要刪除dfs目錄下的name資料夾

相關文章