Hadoop-->分布式系统基础架构-->解决海量数据的存储和分析计算问题
Hadoop三大发行版本:Apache、Cloudera、Hortonworks。
Hadoop的优势:
    1)高可靠性: Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失。
    2)高扩展性:在集群间分配任务数据,可方便的扩展数以千计的节点。
    3)高效性:在MapReduce的思想下,Hadoop是并行工作的,以加快任务处理速度。
    4)高容错性:能够自动将失败的任务重新分配。
Hadoop组成:  Hadoop1.x组成:MapReduce(计算+资源调度)、HDFS(数居存储)、Common(辅助工具)
             Hadoop2.x组成:MapReduce(计算)、Yarn(资源调度)、HDFS (数据存储)、Common(辅助工具)
HDFS架构:
    1)NameNode (nn):存储文件的元数据,如文件名,文件目录结构,文件属性(生成时间、副本数、文件权限),块列表和块所在的DataNode等。
    2)DataNode (dn):在本地文件系统存储文件块数据,以及块数据的校验和。
    3)Secondary NameNode( 2nn):每隔一段时间对NameNode元数据备份。
YARN架构:
    1)ResourceManager (RM)主要作用如下:处理客户端请求、监控NodeManager、启动或监控ApplicationMaster、资源的分配与调度
    2)NodeManager (NM)主要作用如下:管理单个节点上的资源、处理来自ResourceManager的命令、处理来自ApplicationMaster的命令
    3)ApplicationMaster (AM)作用如下:负责数据的切分、为应用程序申请资源并分配给内部的任务、任务的监控与容错
    4)Container:container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等。
MapReduce架构:
    1)Map阶段并行处理输入数据
    2)Reduce阶段对Map结果进行汇总

Hadoop运行环境搭建:
    安装必要插件:yum install -y epel-release      
                yum install -y psmisc nc net-tools rsync vim lrzsz ntp libzstd openssl-static tree iotop git
    修改主机名:hostnamectl --static set-hostname 主机名
    配置主机名称映射:sudo vim /etc/hosts  -->192.168.1.100 主机名 换行192.168.1.101 主机名等
    关闭防火墙:systemctl stop firewalld、systemctl disable firewalld
    创建用户:useradd 用户名    passwd 密码 
    配置用户具有root权限:修改/etc/sudoers文件-->## Allow root to run any commands anywhere
                                                root    ALL=(ALL)     ALL
                                                atguigu   ALL=(ALL)    NOPASSWD:ALL
    创建module、software文件夹-->mkdir module    mkdir software
    修改module、software文件夹的所有者:chown 所属主:所属组 /opt/module /opt/software
    安装JDK:卸载现有JDK-->rpm -qa | grep -i java | xargs -n1 sudo rpm -e --nodeps
            解压JDK到/opt/module目录下:tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/
            配置环境变量:sudo vim /etc/profile.d/my_env.sh      #JAVA_HOME
                                                                export JAVA_HOME=/opt/module/jdk1.8.0_212
                                                                export PATH=$PATH:$JAVA_HOME/bin
    查看jdk版本测试JDK是否安装成功:java -version
    也可以yum安装
安装hadoop:
    Hadoop下载地址:https://archive.apache.org/dist/hadoop/common/hadoop-3.1.3/
    解压安装-->Hadoop添加到环境变量
    sudo vim /etc/profile.d/my_env.sh   ##HADOOP_HOME
                                        export HADOOP_HOME=/opt/module/hadoop-3.1.3
                                        export PATH=$PATH:$HADOOP_HOME/bin
                                        export PATH=$PATH:$HADOOP_HOME/sbin
    (1)bin目录:存放对Hadoop相关服务(HDFS,YARN)进行操作的脚本
    (2)etc目录:Hadoop的配置文件目录,存放Hadoop的配置文件
    (3)lib目录:存放Hadoop的本地库(对数据进行压缩解压缩功能)
    (4)sbin目录:存放启动或停止Hadoop相关服务的脚本
    (5)share目录:存放Hadoop的依赖jar包、文档、和官方案例
    
    本地运行模式:
    hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount 源文件 输出文件(自动创建,不能已经存在)
完全分布式运行模式:
    1)准备多台客户机(关闭防火墙、静态ip、主机名称)
    2)安装JDK
    3)配置环境变量
    4)安装Hadoop
    5)配置环境变量
    6)配置集群
    7)单点启动
    8)配置ssh
    9)群起并测试集群
    
        编写集群分发脚本xsync(详见脚本):scp(secure copy)安全拷贝
        scp    -r          $pdir/$fname              $user@hadoop$host:$pdir/$fname
        命令   递归       要拷贝的文件路径/名称    目的用户@主机:目的路径/名称
        刷新文件:source /etc/profile
        
        rsync远程同步工具:主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点
        rsync和scp区别:用rsync做文件的复制要比scp的速度快,rsync只对差异文件做更新。scp是把所有文件都复制过去。
        rsync    -av       $pdir/$fname              $user@hadoop$host:$pdir/$fname
        命令   选项参数   要拷贝的文件路径/名称    目的用户@主机:目的路径/名称
        -a-->归档拷贝   -v-->显示复制过程
    SSH无密登录配置
        生成公钥和私钥:ssh-keygen -t rsa    然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
        公钥拷贝到要免密登录的目标机器上:ssh-copy-id 主机名
        .ssh文件夹下    known_hosts-->记录ssh访问过计算机的公钥  id_rsa-->生成的私钥  id_rsa.pub-->生成的公钥  
                        authorized_keys-->存放授权过的无密登录服务器公钥
    集群配置:
        NameNode和SecondaryNameNode不要安装在同一台服务器。
        ResourceManager也很消耗内存,不要和NameNode、SecondaryNameNode配置在同一台机器上。

核心配置文件:
         core-site.xml配置:
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 <configuration>
 <!--指定HDFS中NameNode的地址 -->
     <property>
         <name>fs.defaultFS</name>
         <value>hdfs://hadoop102:9820</value>
 </property>
 <!-- 指定Hadoop运行时产生文件的存储目录 -->
     <property>
         <name>hadoop.tmp.dir</name>
         <value>/opt/module/hadoop-3.1.3/data</value>
 </property>
 <!--  通过web界面操作hdfs的权限 -->
 <property>
         <name>hadoop.http.staticuser.user</name>
         <value>atguigu</value>
 </property>
 <!-- hive的兼容性配置  -->
     <property>
         <name>hadoop.proxyuser.atguigu.hosts</name>
         <value>*</value>
     </property>
     <property>
         <name>hadoop.proxyuser.atguigu.groups</name>
         <value>*</value>
 </property>
 </configuration>        hdfs-site.xml配置:
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?><configuration>
     <property>
         <name>dfs.namenode.secondary.http-address</name>
         <value>hadoop104:9868</value>
     </property>
 </configuration>        yarn-site.xml配置:
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?><configuration>
 <!--  Reducer获取数据的方式-->
     <property>
         <name>yarn.nodemanager.aux-services</name>
         <value>mapreduce_shuffle</value>
 </property>
 <!--  指定YARN的ResourceManager的地址-->
     <property>
         <name>yarn.resourcemanager.hostname</name>
         <value>hadoop103</value>
 </property>
 <!-- 环境变量通过从NodeManagers的容器继承的环境属性,对于mapreduce应用程序,除了默认值 hadoop op_mapred_home应该被添加外。属性值 还有如下-->
     <property>
         <name>yarn.nodemanager.env-whitelist</name>
 <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
 </property>
 <!-- 解决Yarn在执行程序遇到超出虚拟内存限制,Container被kill  -->
     <property>
         <name>yarn.nodemanager.pmem-check-enabled</name>
         <value>false</value>
     </property>
     <property>
         <name>yarn.nodemanager.vmem-check-enabled</name>
         <value>false</value>
     </property>
 <!-- hive的兼容性配置  -->
     <property>
         <name>yarn.scheduler.minimum-allocation-mb</name>
         <value>512</value>
     </property>
     <property>
         <name>yarn.scheduler.maximum-allocation-mb</name>
         <value>4096</value>
     </property>
     <property>
         <name>yarn.nodemanager.resource.memory-mb</name>
         <value>4096</value>
 </property>
 </configuration>        mapred-site.xml配置:
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 <configuration>
 <!-- 指定MR运行在Yarn上 -->
     <property>
         <name>mapreduce.framework.name</name>
         <value>yarn</value>
     </property>
 </configuration>        配置历史服务器:mapred-site.xml
 <!-- 历史服务器端地址 -->
 <property>
     <name>mapreduce.jobhistory.address</name>
     <value>hadoop102:10020</value>
 </property><!-- 历史服务器web端地址 -->
 <property>
     <name>mapreduce.jobhistory.webapp.address</name>
     <value>hadoop102:19888</value>
 </property>        配置日志的聚集:yarn-site.xml
 <!-- 开启日志聚集  -->
 <property>
     <name>yarn.log-aggregation-enable</name>
     <value>true</value>
 </property>
 <!-- 访问路径-->
 <property>  
     <name>yarn.log.server.url</name>  
     <value>http://hadoop102:19888/jobhistory/logs</value>
 </property>
 <!-- 保存的时间7天 -->
 <property>
     <name>yarn.log-aggregation.retain-seconds</name>
     <value>604800</value>
 </property>分发配置好的Hadoop配置文件
    群起集群:配置workers: vim /opt/module/hadoop-3.1.3/etc/hadoop/workers文件中添加主机名
                             注意:该文件中添加的内容结尾不允许有空格,文件中不允许有空行。所有节点配置文件
                             
     启动集群:
         集群是第一次启动:需要在NameNode配置节点格式化NameNode
         (注意格式化之前,一定要先停止上次启动的所有namenode和datanode进程,然后再删除data和log数据)
         格式化命令:hdfs namenode -format
         启动HDFS:sbin/start-dfs.sh      启动YARN:sbin/start-yarn.sh
         解决看不到2nn的web页面:路径:$HADOOP_HOME/share/hadoop/hdfs/webapps/static     dfs-dust.js的第61行
         return moment(Number(v)).format('ddd MMM DD HH:mm:ss ZZ YYYY');改为return new Date(Number(v)).toLocaleString();
         各个服务组件逐一启动/停止:hdfs --daemon start/stop namenode/datanode/secondarynamenode
                                    yarn --daemon start/stop  resourcemanager/nodemanager
         各个模块分开启动/停止(配置ssh是前提)常用:start-dfs.sh/stop-dfs.sh
                                                     start-yarn.sh/stop-yarn.sh
     集群时间同步:找一个机器,作为时间服务器,所有的机器与这台集群时间进行定时的同步(root用户)
         关闭ntp服务和自启动:sudo systemctl stop ntpd   sudo systemctl disable ntpd   
         修改ntp配置文件:sudo vim /etc/ntp.conf
                         #所有机器可以从这台机器上查询和同步时间
                         restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
                         #集群在局域网中,不使用其他互联网上的时间
                         #server 0.centos.pool.ntp.org iburst
                         #server 1.centos.pool.ntp.org iburst
                         #server 2.centos.pool.ntp.org iburst
                         #server 3.centos.pool.ntp.org iburst
                         #当该节点丢失网络连接,依然可以采用本地时间作为时间服务器为集群中的其他节点提供时间同步
                         server 127.127.1.0
                         fudge 127.127.1.0 stratum 10
         修改/etc/sysconfig/ntpd 文件:sudo vim /etc/sysconfig/ntpd
                                       #让硬件时间与系统时间一起同步
                                       SYNC_HWCLOCK=yes
         重新启动ntpd服务:systemctl restart ntpd
         设置ntpd服务开机启动:systemctl enable ntpd
         
         其他机器配置(必须root用户):
         配置10分钟与时间服务器同步一次:crontab -e
                                         */10 * * * * /usr/sbin/ntpdate hadoop102
         
         Hadoop编译源码:采用root角色编译,减少文件夹权限出现问题
             jar包准备(hadoop源码、JDK8、maven、ant 、protobuf)
             (1)hadoop-3.1.3-src.tar.gz
             (2)jdk-8u212-linux-x64.tar.gz
             (3)apache-ant-1.9.9-bin.tar.gz(build工具,打包用的)
             (4)apache-maven-3.0.5-bin.tar.gz
             (5)protobuf-2.5.0.tar.gz(序列化的框架)
             Jar包安装
                 JDK解压、配置环境变量 JAVA_HOME和PATH,验证java-version(如下都需要验证是否配置成功)
                 Maven解压、配置  MAVEN_HOME和PATH
                     vi conf/settings.xml:
 <mirrors>
     <!-- mirror
      | Specifies a repository mirror site to use instead of a given repository. The repository that
      | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
      | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
      |
 <mirror>
        <id>mirrorId</id>
        <mirrorOf>repositoryId</mirrorOf>
        <name>Human Readable Name for this Mirror.</name>
        <url>http://my.repository.com/repo/path</url>
       </mirror>
      -->
         <mirror>
                 <id>nexus-aliyun</id>
                 <mirrorOf>central</mirrorOf>
                 <name>Nexus aliyun</name>
                 <url>http://maven.aliyun.com/nexus/content/groups/public</url>
         </mirror>
 </mirrors>                 ant解压、配置  ANT _HOME和PATH
                 安装  glibc-headers 和  g++  命令如下:yum install glibc-headers    yum install gcc-c++
                 安装make和cmake:yum install make    yum install cmake    
                 解压protobuf ,进入到解压后protobuf主目录,/opt/module/protobuf-2.5.0,然后相继执行命令
                     tar -zxvf protobuf-2.5.0.tar.gz -C /opt/module/
                      cd /opt/module/protobuf-2.5.0/
                      ./configure 
                       make 
                       make check
                       make install
                       ldconfig 
                       vi /etc/profile
 #LD_LIBRARY_PATH
 export LD_LIBRARY_PATH=/opt/module/protobuf-2.5.0
 export PATH=$PATH:$LD_LIBRARY_PATH                      source /etc/profile
                 安装openssl库:yum install openssl-devel
                 安装 ncurses-devel库:yum install ncurses-devel
                 
                 编译源码:解压源码到/opt/目录:tar -zxvf hadoop-3.1.3-src.tar.gz -C /opt/
                           进入到hadoop源码主目录:pwd
                           通过maven执行编译命令:mvn package -Pdist,native -DskipTests -Dtar
                           等待,成功的64位hadoop包在/opt/hadoop-3.1.3-src/hadoop-dist/target下
                       
                       
                       
                       
 Hadoop-->HDFS:
     分布式文件管理系统:一种系统来管理多台机器上的文件,HDFS只是分布式文件管理系统中的一种。
     HDFS (Hadoop Distributed File System),一个文件系统,存储文件,通过目录树来定位文件;是分布式的,适合一次写入,多次读出的场景,且不支持文件的修改。
     
     优点:
     1)高容错
         (1)数据自动保存多个副本。它通过增加副本的形式,提高容错性。
         (2)某一个副本丢失以后,它可以自动恢复。
     2)适合处理大数据
         (1)数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;
         (2)文件规模:能够处理百万规模以上的文件数量,数量相当之大。
     3)可构建在廉价机器上,通过多副本机制,提高可靠性。
     缺点
     1)不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
     2)无法高效的对大量小文件进行存储。
         (1)存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
         (2)小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
     3)不支持并发写入、文件随机修改。
         (1)一个文件只能有一个写,不允许多个线程同时写;
         (2)仅支持数据append(追加),不支持文件的随机修改。
     hdfs架构
         1)NameNode (nn):就是Master,它是一个主管、管理者。
             (1)管理HDFS的名称空间;
             (2)配置副本策略;
             (3)管理数据块((Block)映射信息;
             (4)处理客户端读写请求。
         2)DataNode:NameNode下达命令,DataNode执行实际的操作。
             (1)存储实际的数据块;
             (2)执行数据块的读/写操作。
         3)Client:就是客户端。
             (1)文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
             (2)与NameNode交互,获取文件的位置信息;
             (3)与DataNode交互,读取或者写入数据;
             (4 ) Client提供一些命令来管理HDFS,比如NameNode格式化;
             (5)Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;
         4)Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
             (1)辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode ;
             (2)在紧急情况下,可辅助恢复NameNode。
     HDFS文件块大小
         HDFS中的文件在物理上是分块存储( Block ) ,块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在Hadoop2.x/版本中是128M,老版本中是64M。
         原因:如果寻址时间约为10ms,即查找到目标block的时间为10ms。寻址时间为传输时间的1%时,则为最佳状态。传输时间=10ms/0.01=1000ms=1s,目前磁盘的传输速率普遍为100MB/s。
         HDFS块的大小设置主要取决于磁盘传输速率。
     hdfs命令
         bin/hadoop fs 具体命令   OR  bin/hdfs dfs 具体命令
         -moveFromLocal:从本地剪切粘贴到HDFS
         -copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去
         -appendToFile:追加一个文件到已经存在的文件末尾
         -put:等同于copyFromLocal
         -copyToLocal:从HDFS拷贝到本地
         -get:等同于copyToLocal,就是从HDFS下载文件到本地
         -getmerge:合并下载多个文件,比如HDFS的目录 /user/atguigu/test下有多个文件:log.1, log.2,log.3,...
         -rmdir:删除空目录
         -du统计文件夹的大小信息
         -setrep:设置HDFS中文件的副本数量
         其他命令基本和Linux相同
     hdfs代码操作
         // 1 获取文件系统
         Configuration configuration = new Configuration();
         // 配置在集群上运行
         configuration.set("fs.defaultFS", "hdfs://主机名:9820");
         // FileSystem fs = FileSystem.get(configuration);
         FileSystem fs = FileSystem.get(new URI("hdfs://主机名:9820"), configuration, "名称");
         // 2 操作过程                
         // 3 关闭资源
         fs.close();
     HDFS写数据流程
         1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
         2)NameNode返回是否可以上传。
         3)客户端请求第一个 Block上传到哪几个DataNode服务器上。
         4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。
         5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
         6)dn1、dn2、dn3逐级应答客户端。
         7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
         8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。
     HDFS读数据流程
         (1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
         (2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
         (3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
         (4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
     NameNode和SecondaryNameNode
     NameNode工作机制
         1)第一阶段:NameNode启动
             (1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
             (2)客户端对元数据进行增删改的请求。
             (3)NameNode记录操作日志,更新滚动日志。
             (4)NameNode在内存中对元数据进行增删改。
         2)第二阶段:Secondary NameNode工作
             (1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
             (2)Secondary NameNode请求执行CheckPoint。
             (3)NameNode滚动正在写的Edits日志。
             (4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
             (5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
             (6)生成新的镜像文件fsimage.chkpoint。
             (7)拷贝fsimage.chkpoint到NameNode。
             (8)NameNode将fsimage.chkpoint重新命名成fsimage。
     Fsimage和Edits解析
         (1)Fsimage文件: HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。
         (2)Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到Edits文件中。
         (3)seen_txid文件保存的是一个数字,就是最后一个edits的数字
         (4)每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimage和Edits文件进行了合并。
         oiv查看Fsimage文件
         路径/opt/module/hadoop-3.1.3/data/tmp/dfs/name/current
         hdfs
         oiv-->apply the offline fsimage viewer to an fsimage
         oev-->apply the offline edits viewer to an edits file
         hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
         hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
     CheckPoint时间设置
         通常情况下,SecondaryNameNode每隔一小时执行一次。
 hdfs-default.xml
 <property>
   <name>dfs.namenode.checkpoint.period</name>
   <value>3600</value>
 </property><property>
   <name>dfs.namenode.checkpoint.txns</name>
   <value>1000000</value>
 <description>操作动作次数</description>
 </property><property>
   <name>dfs.namenode.checkpoint.check.period</name>
   <value>60</value>
 <description> 1分钟检查一次操作次数</description>
 </property >    NameNode故障处理
         将SecondaryNameNode中数据拷贝到NameNode存储数据的目录
             1)关闭namenode
             2)删除NameNode存储的数据(/opt/module/hadoop-3.1.3/data/tmp/dfs/name)
             3)拷贝SecondaryNameNode中数据到原NameNode存储数据目录
             4)重新启动NameNode
         使用-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode中数据拷贝到NameNode目录中。
             1)修改hdfs-site.xml
 <property>
     <name>dfs.namenode.checkpoint.period</name>
     <value>120</value>
 </property><property>
     <name>dfs.namenode.name.dir</name>
     <value>/opt/module/hadoop-3.1.3/data/tmp/dfs/name</value>
 </property>
             2)关闭namenode
             3)删除NameNode存储的数据(/opt/module/hadoop-3.1.3/data/tmp/dfs/name)
             4)SecondaryNameNode不和NameNode在一个主机节点,将SecondaryNameNode存储数据的目录拷贝到NameNode存储数据的平级目录,删除in_use.lock文件
             5)导入检查点数据(等待一会ctrl+c结束掉)
                 bin/hdfs namenode -importCheckpoint
             6)启动NameNode
     DataNode工作机制
         1)一个数据块在DataNode上以文件形式存储在磁盘,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
         2)DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。
         3)心跳3秒一次,心跳返回带有NameNode给DataNode的命令,超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
         4)集群运行中可以安全加入和退出一些机器。
     数据完整性
         1)当DataNode读取Block的时候,它会计算CheckSum。
         2)如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
         3)Client读取其他DataNode上的Block。
         4)DataNode在其文件创建后周期验证CheckSum。
     DataNode掉线时限参数设置
         1)DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信
         2)NameNode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。
         3)HDFS默认的超时时长为10分钟+30秒。
         4)如果定义超时时间为TimeOut,则超时时长的计算公式为:
             TimeOut = 2*dfs.namenode.heartbeat.recheck-interval+ 10 * dfs.heartbeat.interval。
             默认:dfs.namenode.heartbeat.recheck-interval 为5分钟,dfs.heartbeat.interval默认为3秒。
             hdfs-site.xml 配置文件
     添加白名单
         添加到白名单的主机节点,都允许访问NameNode,不在白名单的主机节点,都会被退出。
         配置白名单:
         路径/opt/module/hadoop-3.1.3/etc/hadoop-->vim dfs.hosts-->添加主机名,换行隔开
         hdfs-site.xml配置文件中增加dfs.hosts属性
 <property>
 <name>dfs.hosts</name>
 <value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts</value>
 </property>
         分发配置文件并刷新NameNode:hdfs dfsadmin -refreshNodes
         更新ResourceManager节点:yarn rmadmin -refreshNodes
         命令实现集群的再平衡:hadoop/sbin/start-balancer.sh
     黑名单退役
         黑名单上面的主机都会被强制退出
         路径/opt/module/hadoop-3.1.3/etc/hadoop-->vim dfs.hosts.exclude-->添加主机名,换行隔开
         hdfs-site.xml配置文件中增加dfs.hosts.exclude属性(并重启NameNode)
 <property>
 <name>dfs.hosts.exclude</name>
       <value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts.exclude</value>
 </property>
         刷新NameNode:hdfs dfsadmin -refreshNodes
         刷新ResourceManager:yarn rmadmin -refreshNodes
         web退役节点的状态为decommission in progress(退役中),说明数据节点正在复制块到其他节点
         退役节点状态为decommissioned(所有块已经复制完成),停止该节点及节点资源管理器。
             hdfs --daemon stop datanode
             sbin/yarn-daemon.sh stop nodemanager
         命令实现集群的再平衡:sbin/start-balancer.sh
     注:如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役
         DataNode也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本
 <property>
 <name>dfs.datanode.data.dir</name>
 <value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
 </property> MapReduce&Yarn
     MapReduce
         MapReduce是分布式运算程序的编程框架,将用户编写的业务逻辑代码和自带默认组件整合成完整的分布式运算程序,并发运行在一个Hadoop集群上
     优点
         1)易于编程,可以分布到大量廉价的机器上运行。
         2)良好的扩展性
             可以通过简单的增加机器来扩展它的计算能力
         3)高容错性
             自己可以把计算任务转移到另外一个节点上运行,不至于这个任务运行失败
         4)适合PB级以上海量数据的离线处理
     缺点
         1)不擅长实时计算
         2)不擅长流式计算
             MapReduce的输入数据集是静态的,不能动态变化
         3)不擅长DAG(有向图)计算
             MapReduce输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低下
     MapReduce核心思想
         1)分布式的运算程序往往需要分成至少2个阶段。
         2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。
         3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
         4)MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果业务逻辑非常复杂,就只能多个MapReduce程序,串行运行
     MapReduce进程
         1)MrAppMaster:负责整个程序的过程调度及状态协调。
         2)MapTask:负责Map阶段的整个数据处理流程。
         3)ReduceTask:负责Reduce阶段的整个数据处理流程。
     数据切片与MapTask并行度决定机制
         1)一个Job的Map阶段并行度由客户端在提交Job时的切片数决定
         2)每一个Split切片分配一个MapTask并行实例处理
         3)默认情况下,切片大小=BlockSize
         4)切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
     框架默认TextInputFormat切片机制对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
     解决:CombineTextInputFormat-->将多个小文件从逻辑上规划到一个切片中
     MapReduce工作流程
         1)MapTask收集我们的map()方法输出的kv对,放到内存缓冲区中
         2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
         3)多个溢出文件会被合并成大的溢出文件
         4)在溢出过程及合并的过程中,都要调用Partitioner进行分区和针对key进行排序
         5)ReduceTask根据自己的分区号,去各个MapTask机器上取相应的结果分区数据
         6)ReduceTask会取到同一个分区的来自不同MapTask的结果文件,ReduceTask会将这些文件再进行合并(归并排序)
         7)合并成大文件后,Shuffle的过程结束进入ReduceTask逻辑运算过程(取出键值对Group,调用自定义的reduce()方法)
     Shuffle机制
     Yarn工作机制
         1)MR程序提交到客户端所在的节点。
         2)YarnRunner向ResourceManager申请一个Application。
         3)RM将该应用程序的资源路径返回给YarnRunner。
         4)该程序将运行所需资源提交到HDFS上。
         5)程序资源提交完毕后,申请运行mrAppMaster。
         6)RM将用户的请求初始化成一个Task。
         7)其中一个NodeManager领取到Task任务。
         8)该NodeManager创建容器Container,并产生MRAppmaster。
         9)Container从HDFS上拷贝资源到本地。
         10)MRAppmaster向RM 申请运行MapTask资源。
         11)RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。
         12)MR向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动MapTask,MapTask对数据分区排序。
         13)MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。
         14)ReduceTask向MapTask获取相应分区的数据。
         15)程序运行完毕后,MR会向RM申请注销自己。
     作业提交全过程
         (1)作业提交
         第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。
         第2步:Client向RM申请一个作业id。
         第3步:RM给Client返回该job资源的提交路径和作业id。
         第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。
         第5步:Client提交完资源后,向RM申请运行MrAppMaster。
         (2)作业初始化
         第6步:当RM收到Client的请求后,将该job添加到容量调度器中。
         第7步:某一个空闲的NM领取到该Job。
         第8步:该NM创建Container,并产生MRAppmaster。
         第9步:下载Client提交的资源到本地。
         (3)任务分配
         第10步:MrAppMaster向RM申请运行多个MapTask任务资源。
         第11步:RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。
         (4)任务运行
         第12步:MR向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动MapTask,MapTask对数据分区排序。
         第13步:MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。
         第14步:ReduceTask向MapTask获取相应分区的数据。
         第15步:程序运行完毕后,MR会向RM申请注销自己。
         (5)进度和状态更新
         YARN中的任务将其进度和状态(包括counter)返回给应用管理器, 客户端每秒(通过mapreduce.client.progressmonitor.pollinterval设置)向应用管理器请求进度更新, 展示给用户。
         (6)作业完成
         除了向应用管理器请求作业进度外, 客户端每5秒都会通过调用waitForCompletion()来检查作业是否完成。时间间隔可以通过mapreduce.client.completion.pollinterval来设置。作业完成之后, 应用管理器和Container会清理工作状态。作业的信息会被作业历史服务器存储以备之后用户核查。
     Hadoop作业调度器主要有三种:FIFO、Capacity Scheduler和Fair Scheduler。
     yarn-default.xml文件
 <property>
     <name>yarn.resourcemanager.scheduler.class</name>
 <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
     <description>The class to use as the resource scheduler.</description>
 </property>