4-Hadoop学习笔记1


大数据概论

大数据概念

  • 大数据:指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产
  • 大数据主要解决,海量数据的采集、存储和分析计算问题

大数据特点(4V)

  • Volume(大量)
  • Velocity(高速)
  • Variety(多样)
  • Value(低价值密度)

Hadoop入门

Hadoop概述

  • Hadoop是什么

    • Hadoop是一个有Apache基金会所开发的分布式系统基础架构,主要解决海量数据的存储和海量数据的分析计算问题。广义来说,Hadoop通常指一个更广泛的概念—Hadoop生态圈
  • Hadoop优势(4高)

    • 高可靠性
      • Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失
    • 高扩展性
      • 在集群间分配任务数据,可方便的扩展数以千计的节点
    • 高效性
      • 在MapReduce的思想下,Hadoop是并行工作的,以加快任务处理速度
    • 高容错性
      • 能够自动将失败的任务重新分配
  • Hadoop组成(重点)

    • HDFS架构概述
      • Hadoop Distributed File System,简称HDFS,是一个分布式文件系统
      • NameNode(nn):存储文件的元数据,如文件名、文件目录结构、文件属性,以及每个文件的块列表和块所在的DataNode等
      • DataNode(dn):在本地文件系统中存储文件块数据,以及块数据的校验和
      • Secondary NameNode(2nn):每隔一段时间对NameNode元数据备份
    • YARN架构概述
      • Yet Another Resource Negotiator简称YARN,另一种资源协调者,是Hadoop的资源管理器
      • ResourceManager(RM):整个集群资源(内存、CPU等)的老大
      • NodeManager(NM):单个节点服务器资源老大
      • ApplicationMaster(AM):单个任务运行老大
      • Container:容器,相当于一台独立的服务器,里面封装了任务运行所需要的资源,如内存、CPU、磁盘、网络等

    • MapReduce架构概述
      • MapReduce将计算过程分为两个阶段:Map和Reduce
      • Map阶段并行处理数据
      • Reduce阶段对Map结果进行汇总
    • HDFS、YARN、MapReduce三者关系

  • 大数据技术生态体系

  • Sqoop:Sqoop是一款开源的工具,主要用于在Hadoop、Hive与传统的数据库(MySQL)间进行数据的传递,可以将一个关系型数据库(例如 :MySQL,Oracle 等)中的数据导进到Hadoop的HDFS中,也可以将HDFS的数据导进到关系型数据库中。

  • Flume:Flume是一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;

  • Kafka:Kafka是一种高吞吐量的分布式发布订阅消息系统;

  • Spark:Spark是当前最流行的开源大数据内存计算框架。可以基于Hadoop上存储的大数据进行计算。

  • Flink:Flink是当前最流行的开源大数据内存计算框架。用于实时计算的场景较多。

  • Oozie:Oozie是一个管理Hadoop作业(job)的工作流程调度管理系统。

  • Hbase:HBase是一个分布式的、面向列的开源数据库。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。

  • Hive:Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行。其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。

  • ZooKeeper:它是一个针对大型分布式系统的可靠协调系统,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。

Hadoop运行环境搭建(重点)

  • 模板虚拟机环境准备

    • 安装模板虚拟机,IP地址192.168.88.100、主机名称hadoop100、内存2G、硬盘50G

    • hadoop100虚拟机配置

      • 使用yum安装需要虚拟机可以正常上网,yum安装前可以先测试下虚拟机联网情况

      • 安装epel-release

        • 注:Extra Packages for Enterprise Linux是为“红帽系”的操作系统提供额外的软件包,适用于RHEL、CentOS和Scientific Linux。相当于是一个软件仓库,大多数rpm包在官方repository中是找不到的

        • yum install -y epel-release
          
      • 如果Linux安装的是最小系统版,还需要安装如下工具

      • net-tool:工具包集合,包含ifconfig等命令

        • yum install -y net-tools
          
      • vim

        • yum install -y vim
          
    • 关闭防火墙,关闭防火墙开机自启

      • 注意企业开发时,通常单个服务器的防火墙是关闭的。公司整体会对外设置非常安全的防火墙

      • systemctl stop firewalld
        systemctl disable firewalld.service
        
    • 创建lotuslaw用户,并修改lotuslaw用户的密码

      • useradd lotuslaw
        passwd lotuslaw
        
    • 配置lotuslaw用户具有root权限,方便后期加sudo执行root权限的命令

      • vim /etc/sudoers
        
      • 修改/etc/sudoers文件,在%wheel这行下面添加一行,如下所示

      • 注意:lotuslaw这一行不要直接放到root行下面,因为所有用户都属于wheel组,你先配置了lotuslaw具有免密功能,但是程序执行到%wheel行时,该功能又被覆盖回需要密码。所以lotuslaw要放到%wheel这行下面
    • 在/opt目录下创建文件夹,并修改所属主和所属组

      • 在/opt目录下创建module、software文件夹

        • mkdir /opt/module
          mkdir /opt/software
          
      • 修改module、software文件夹的所有者和所属组均为lotuslaw用户

        • chown lotuslaw:lotuslaw /opt/module
          chown lotuslaw:lotuslaw /opt/software
          
      • 查看module、software文件夹的所有者和所属组

    • 卸载虚拟机自带的JDK

      • 注意:如果你的虚拟机是最小化安装,则不需要执行这一步

      • rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps
        
        • rpm -qa:查询所安装的所有rpm软件包
        • grep -i:忽略大小写
        • xargs -n1:表示每次只传递一个参数
        • rpm -e -nodeps:强制卸载软件
    • 重启虚拟机

      • reboot
        
  • 克隆虚拟机

    • 利用模板机hadoop100,克隆三台虚拟机:hadoop102、hadoop103、hadoop104

      • 注意:克隆时,要先关闭hadoop100
    • 修改克隆机IP,以下以hadoop102举例说明

      • 修改克隆虚拟机的静态ip

        • vim /etc/sysconfig/network-scripts/ifcfg-ens33
          
        • 改成

      • 查看Linux虚拟机的虚拟网络编辑器,编辑>>虚拟网络编辑器>>VMnet8

      • 查看Windows系统适配器VMware Network Adapter VMnet8的IP地址

      • 保证Linux系统ifcfg-ens33文件中的IP地址、虚拟网络编辑器地址和Windows系统VM8网络IP地址相同

    • 修改克隆机主机名,以下以hadoop102举例说明

      • 修改主机名称

        • vim /etc/hostname
          
        • 改为hadoop102

      • 配置Linux克隆机主机名映射hosts文件,打开/etc/hosts

        • vim /etc/hosts
          
        • 添加如下内容

    • 重启克隆机hadoop102

      • reboot
        
    • 修改Windows的主机映射文件(hosts文件)

      • 进入C:\Windows\System32\drivers\etc路径
      • 拷贝hosts文件到桌面,打开桌面hosts文件并添加如下内容,将桌面修改后的文件覆盖原路径文件

  • 在hadoop102安装JDK

    • 卸载现有JDK

    • 用Xshell传输工具(Xftp)将JDK导入到opt目录下面的software文件夹下面

    • 在Linux系统下的opt目录中查看软件包是否导入成功

      • ls /opt/software/
        
    • 解压JDK到/opt/module目录下

      • tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/
        
    • 配置JDK环境变量

      • 新建/etc/profile.d/my_env.sh文件

      • sudo vim /etc/profile.d/my_env.sh
        
      • 添加如下内容

      • 保存后退出,source一下/etc/profile文件,让新的环境变量PATH生效

        • source /etc/profile
          
    • 测试JDK是否安装成功

      • java -version
        
    • 重启

      • sudo reboot
        
  • 在hadoop102安装Hadoop

    • 用Xshell文件传输工具将hadoop-3.1.3.tar.gz导入到opt目录下面的software文件夹下面

    • 进入到Hadoop安装包路径下

      • cd /opt/software/
        
    • 解压到/opt/module下面

      • tar -zxvf hadoop-3.1.3.tar.gz -C /opt/module
        
    • 查看解压是否成功

      • ls /opt/module
        
    • 将Hadoop添加到环境变量

      • 打开/etc/profile.d/my_env.sh文件,添加如下内容:

      • 保存退出,source一下/etc/profile
    • 测试是否安装成功

      • hadoop version
        
    • 重启

      • sudo reboot
        
  • Hadoop目录结构

    • 查看Hadoop目录结构

    • 重要目录
      • bin目录:存放对Hadoop相关服务(hdfs,yarn,mapred)进行操作的脚本
      • etc目录:Hadoop的配置文件目录,存放Hadoop的配置文件
      • lib目录:存放Hadoop的本地库(对数据进行压缩解压缩功能)
      • sbin目录:存放启动或停止Hadoop相关服务的脚本
      • share目录:存放Hadoop的依赖jar包、文档、和官方案例

Hadoop运行模式

  • 概述

    • Hadoop运行模式包括:本地模式、伪分布模式以及完全分布模式
      • 本地模式:单机运行,只是用来演示一下官方案例。生产环境不用
      • 伪分布模式:也是单机运行,但是具备Hadoop集群的所有功能,一台服务器模拟一个分布式的环境。
      • 完全分布式模式:多台服务器组成分布式环境
  • 本地运行模式(官方WordCount)

    • 自己准备word.txt文件

    • hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount wcinput/ wcoutput/
      
    • 查看结果

      • cat wcoutput/part-r-00000
        
  • 完全分布式运行模式(重点)

    • 内容

      • 准备3台客户机(关闭防火墙、静态IP、主机名称)
      • 安装JDK
      • 配置环境变量
      • 安装Hadoop
      • 配置环境变量
      • 配置集群
      • 单点启动
      • 配置ssh
      • 群起并测试集群
    • 虚拟机准备

    • 编写集群分发脚本xsync

      • scp(secure copy)安全拷贝

        • scp定义

          • scp可以实现服务器与服务器之间的数据拷贝
        • 基本语法

          • scp -r $pdir/$fname $user@$host:$pdir/$fname
            # 命令 递归 要拷贝的文件路径/名称 目的地用户/@主机:目的地路径/名称
            
      • rsync远程同步工具

        • rsync主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点

        • rsync和scp区别:用rsync做文件的复制要比scp速度快,rsync只对差异文件做更新。scp是吧所有文件都复制过去

        • 基本语法

          • rsync -av $pdir/$fname $user@$host:$pdir/$fname
            # 命令 选项参数 要拷贝的文件路径/名称 目的地用户/@主机:目的地路径/名称
            # -a 归档拷贝
            # -v 显示复制过程
            
      • xsync集群分发脚本

        • 需求:循环复制文件到所有节点的相同目录下

        • 在/home/lotuslaw/bin目录下创建xsync文件,在该文件中编写如下代码

          • #!/bin/bash
            
            #1. 判断参数个数
            if [ $# -lt 1 ]
            then
                echo Not Enough Arguement!
                exit;
            fi
            #2. 遍历集群所有机器
            for host in hadoop102 hadoop103 hadoop104
            do
                echo ====================  $host  ====================
                #3. 遍历所有目录,挨个发送
            
                for file in $@
                do
                    #4. 判断文件是否存在
                    if [ -e $file ]
                        then
                            #5. 获取父目录
                            pdir=$(cd -P $(dirname $file); pwd)
            
                            #6. 获取当前文件的名称
                            fname=$(basename $file)
                            ssh $host "mkdir -p $pdir"
                            rsync -av $pdir/$fname $host:$pdir
                        else
                            echo $file does not exists!
                    fi
                done
            done
            
        • 修改脚本xsync具有执行权限

          • chmod +x xsync
            
        • 测试脚本

          • xsync /home/lotuslaw/bin
            
        • 将脚本复制到/bin中,以便全局调用

          • sudo cp xsync /bin/
            
        • 同步环境变量配置(root所有者)

          • sudo ./bin/xsync/etc/profile.d/my_env.sh
            # 注意:如果用了sudo,那么xsync一定要给它的路径补全
            
        • 让环境变量生效

          • # 分别在103和104机器source
            source /etc/profile
            
    • SSH无密登录配置

      • 基本语法

        • ssh另一台电脑的IP地址
      • 无密钥配置

        • 免密登录原理

      • 生成公钥和私钥

        • cd /home/lotuslaw/.ssh
          ssh-keygen -t rsa
          # 然后敲三个回车,就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
          
      • 将公钥拷贝到需要免密登录的目标机器上

        • ssh-copy-id hadoop102
          ssh-copy-id hadoop103
          ssh-copy-id hadoop104
          
        • 注意:需要在每台机器上配置

      • .ssh文件夹下的文件功能解释

        • known_hosts:记录ssh访问过计算机的公钥
        • id_rsa:生成的私钥
        • id_rsa.pub:生成的公钥
        • authorized_keys:存放授权过的无密登录服务器公钥
    • 集群配置

      • 集群部署规划

        • NameNode和SecondaryNameNode不要安装在同一台服务器

        • ResourceManager也很消耗内存,不要和NameNode、SecondaryNameNode配置在同一台机器上

        • hadoop102 hadoop103 hadoop104
          HDFS NameNode、DataNode DataNode SecondaryNameNode、DataNode
          YARN NodeManager ResourceManager、NodeManager NodeManager
      • 配置文件说明

        • Hadoop配置文件分为两类:默认配置文件和自定义配置文件,只有用户想修改某一默认配置时,才需要修改自定义配置文件,更改相应属性值
        • 默认配置文件
          • core-default.xml、hdfs-default.xml、yarn-default.xml、mapred-default.xml
        • 自定义配置文件
          • core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml
          • 四个配置文件存在$HADOOP_HOME/hadoop这个路径上,用户可以根据项目需求重新进行修改配置
      • 配置集群

        • 核心配置文件

        • cd $HADOOP_HOME/etc/hadoop
          vim core-site.xml
          

      • HDFS配置文件

        • vim hdfs-site.xml
          

      • YARN配置

        • vim yarn-site.xml
          

      • MapReduce配置文件

        • vim mapred-site.xml
          

      • 在集群上分发配置好的Hadoop配置文件

        • xsync /opt/module/hadoop-3.1.3/etc/hadoop/
          
      • 去103和104上查看文件分发情况

    • 群起集群

      • 配置workers

        • vim /opt/module/hadoop-3.1.3/etc/hadoop/workers
          
        • 在文件中增加如下内容

        • 注意:该文件中添加到内容结尾不允许有空格,文件中不允许有空行
        • 同步所有节点配置文件
      • 启动集群

        • 如果集群是第一次启动,需要在hadoop102节点格式化NameNode(注意:格式化NameNode,会产生新的集群id,导致NameNode和DataNode的集群id不一致,集群找不到已往数据。如果集群在运行过程中报错,需要重新格式化NameNode的话,一定要先停止namenode和datanode进程,并且要删除所有集群的data和logs目录,然后再进行格式化)

          • hdfs namenode -format
            
        • 启动HDFS

          • sbin/start-dfs.sh
            
        • 在配置了ResourceManager的节点(hadoop103)启动YARN

          • sbin/start-yarn.sh
            
        • Web端查看HDFS的NameNode

          • 在浏览器输入:http://hadoop102:9870
          • 查看HDFS上存储的数据信息
        • Web端查看YARN的ResourceManager

          • 在浏览器中输入:http://hadoop103:8088
          • 查看YARN上运行的Job信息
      • 集群基本测试

    • 配置历史服务器

      • 为了查看程序的历史运行情况,需要配置一下历史服务器

      • 配置mapred-site.xml

        • vim mapred-site.xml
          

      • 分发配置

        • xsync $HADOOP_HOME/etc/hadoop/mapred-site.xml
          
      • 在hadoop102启动历史服务器

        • mapred --daemon start historyserver
          
      • 查看历史服务器是否启动

        • jps
          
      • 查看JobHistory

        • http://hadoop102:19888/jobhistory
    • 配置日志的聚集

      • 日志聚集概念:应用运行完成以后,将程序运行日志信息上传到HDFS系统上

      • 日志聚集功能好处:可以方便的查看到程序运行详情,方便开发调试。注意:开启日志聚集功能,需要重新启动NodeManager、ResourceManager、HistoryServer
      • 配置yarn-site.xml

      • 分发配置

        • xsync $HADOOP_HOME/etc/hadoop/yarn-site.xml
          
      • 关闭NodeManager、ResourceManager和HistoryServer

        • sbin/stop-yarn.sh
          mapred --daemon stop historyserver
          
      • 启动NodeManager、ResourceManager和HistoryServer

        • start-yarn.sh
          mapred --daemon start historyserver
          
      • 删除HDFS上已经存在的输出文件

        • hadoop fs -rm -r /output
          
      • 执行WordCount程序

        • hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output
          
      • 查看日志

        • http://hadoop102:19888/jobhistory
    • 集群启动/停止方式总结

      • 各个模块分开启动/停止(配置ssh是前提)

        • 整体启动/停止HDFS

          • start-dfs.sh/stop-dfs.sh
            
        • 整体启动/停止YARN

          • start-yarn.sh/stop-yarn.sh
            
      • 各个服务组件逐一启动/停止

        • 分别启动/停止HDFS组件

          • hdfs --daemon start/stop namenode/datanode/secondarynamenode
            
        • 分别启动/停止YARN

          • yarn --daemon start/stop resourcemanager/nodemanager
            
    • 编写Hadoop集群常用脚本

      • Hadoop集群启停脚本(包含HDFS,YARN,HistoryServer):myhadoop.sh

        • cd /home/lotuslaw/bin
          vim myhadoop.sh
          
        • 输入如下内容

        • #!/bin/bash
          
          if [ $# -lt 1 ]
          then
              echo "No Args Input..."
              exit ;
          fi
          
          case $1 in
          "start")
                  echo " =================== 启动 hadoop集群 ==================="
          
                  echo " --------------- 启动 hdfs ---------------"
                  ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/start-dfs.sh"
                  echo " --------------- 启动 yarn ---------------"
                  ssh hadoop103 "/opt/module/hadoop-3.1.3/sbin/start-yarn.sh"
                  echo " --------------- 启动 historyserver ---------------"
                  ssh hadoop102 "/opt/module/hadoop-3.1.3/bin/mapred --daemon start historyserver"
          ;;
          "stop")
                  echo " =================== 关闭 hadoop集群 ==================="
          
                  echo " --------------- 关闭 historyserver ---------------"
                  ssh hadoop102 "/opt/module/hadoop-3.1.3/bin/mapred --daemon stop historyserver"
                  echo " --------------- 关闭 yarn ---------------"
                  ssh hadoop103 "/opt/module/hadoop-3.1.3/sbin/stop-yarn.sh"
                  echo " --------------- 关闭 hdfs ---------------"
                  ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/stop-dfs.sh"
          ;;
          *)
              echo "Input Args Error..."
          ;;
          esac
          
        • 保存退出后,然后赋予脚本执行权限

          • chmod +x myhadoop.sh
            
      • 查看三台服务器Java进程脚本:jpsall

        • cd /home/lotuslaw/bin
          vim jpsall
          
        • 输入如下内容

        • #!/bin/bash
          
          for host in hadoop102 hadoop103 hadoop104
          do
                  echo =============== $host ===============
                  ssh $host jps 
          done
          
        • 保存退出后赋予脚本执行权限

          • chmod +x jpsall
            
        • 分发/home/lotuslaw/bin目录,保证自定义脚本在三台机器上都可以使用

          • xsync /home/lotuslaw/bin
            

    • 常用端口号说明

      • 端口名称 Hadoop2.x Hadoop3.x
        NameNode内部通信端口 8020/9000 8020/9000/9820
        NameNode HTTP UI 50070 9870
        MapReduce查看执行任务端口 8088 8088
        历史服务器通信端口 19888 19888
    • 集群时间同步

      • 如果服务器在公网环境(能连接外网),可以不采用集群时间同步,因为服务器会定期和公网时间进行校准

      • 如果服务器在内网环境,必须要配置集群时间同步,否则时间久了,会产生时间偏差,导致集群执行任务时间不同步

      • 需求:寻找一个机器,作为时间服务器,所有的机器与这台机器时间进行定时的同步,生产环境根据任务对时间的准确程度要求周期同步。测试环境为了尽快看到效果,采用1分钟同步一次

      • 时间服务器配置(必须root用户)

        • 查看所有节点ntpd服务状态和开机自启动状态

          • sudo systemctl status ntpd
            sudo systemctl start ntpd
            sudo systemctl is-enabled ntpd
            
        • 修改hadoop102的ntp.conf配置文件

          • 授权192.168.88.0-192.168.88.255网段上所有的机器可以从这台机器上查询和同步时间

            • sudo vim /etc/ntp.conf
              
            • 修改为

            • restrict 192.168.88.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
              
        • 修改hadoop102的/etc/sysconfig/ntpd文件

          • sudo vim /etc/sysconfig/ntpd
            
          • 增加内容如下(让硬件时间与系统时间一起同步)

          • SYNC_HWCLOCK=yes
            
          • 重启ntpd服务

            • sudo systemctl start ntpd
              
          • 设置ntpd服务开机自启动

            • sudo systemctl enable ntpd
              
        • 其他机器配置(必须root用户)

          • 关闭所有节点ntp服务和自启动

            • sudo systemctl stop ntpd
              sudo systemctl disable ntpd
              
          • 在其他机器配置1分钟与时间服务器同步一次

            • sudo crontab -e
              
            • 编写定时任务如下:

            • */1 * * * * /usr/sbin/ntpdate hadoop102
              
            • 修改任意机器时间

              • sudo date -s "2021-9-11 11:11:11"
                
            • 1分钟后查看机器是否与时间服务器同步

              • sudo date
                

常见错误及解决方案

  • 防火墙没关闭、或者没有启动YARN

    • INFO client.RMProxy: Connecting to ResourceManager at hadoop108/192.168.88.108:8032
  • 主机名配置错误

  • IP地址配置错误

  • ssh没有配置好

  • root用户和lotuslaw两个用户启动集群不统一

  • 配置文件修改不细心

  • 不识别主机名称

    • java.net.UnknownHostException: hadoop102: hadoop102
              at java.net.InetAddress.getLocalHost(InetAddress.java:1475)
              at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:146)
              at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290)
              at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287)
              at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.Subject.doAs(Subject.java:415)
      
    • 解决办法

      • 在/etc/hosts文件中添加192.168.88.102 hadoop102
      • 主机名不要其hadoop hadoop000等特殊名称
  • DataNode和NameNode进程同时只能工作一个

  • jps发现进程已经没有,但是重新启动集群,提示进程已经开启

    • 原因:在Linux的根目录/tmp目录中存在启动的进程临时文件,将集群相关进程删除掉,再重新启动集群
  • jps不生效

    • 原因:全局变量hadoop java没有生效
    • 解决办法:需要source /etc/profile问价
  • 8088端口连接不上

    • vim /etc/hosts
      
    • 注释掉

    • #127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
      #::1         hadoop102
      

HDFS

HDFS概述

  • HDFS产出背景及定义

    • HDFS产生背景
      • 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种
    • HDFS定义
      • HDFS是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色
      • HDFS的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变
  • HDFS优缺点

    • 优点
      • 高容错性
        • 数据自动保存多个副本,它通过增加副本的形式,提高容错性,某一个副本丢失以后,它可以自动恢复
      • 实例处理大数据
        • 数据规模大
        • 文件规模(数量)大
      • 可构建在廉价机器上,通过多副本机制,提高可靠性
    • 缺点
      • 不适合低时延数据访问
      • 无法高效的对大量小文件进行存储
        • NameNode的内存总是有限的
        • 小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标
      • 不支持并发写入、文件随机修改
        • 一个文件只能有一个写,不允许多个线程同时写
        • 仅支持数据append(追加),不支持文件的随机修改
  • HDFS组成架构

    • NameNode(nn):就是Master,它是一个主管、管理者
      • 管理HDFS的名称空间
      • 配置副本策略
      • 管理数据块(Block)映射信息
      • 处理客户端读写请求
    • DataNode:就是Slave,NameNode下达命令,DataNode执行实际的操作
      • 存储实际的数据块
      • 执行数据块的读写操作
    • Client:就是客户端
      • 文件切分,w文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传
      • 与NameNode交互,获取文件的位置信息
      • 与DataNode交互,读取或者写入数据
      • Client提供一些命令来管理HDFS,比如NameNode格式化
      • Client可以通过一些命令来访问HDFS,比如NameNode格式化
    • SecondaryNameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务
      • 辅助NameNode,分担其工作量,比如定期合并FsImage和Edits,并推送给NameNode
      • 在紧急情况下,可以辅助恢复NameNode
  • HDFS文件块大小

    • HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中64M

    • 为什么块的大小不能设置太小,也不能设置太大?
      • HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置
      • 如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。导致程序在处理这块数据时,会非常慢
      • HDFS块的大小设置主要取决于磁盘的传输速率

HDFS的Shell操作(重点)

  • 基本语法

    • hadoop fs 具体命令 OR hdfs dfs 具体命令,两者完全相同
  • 命令大全

    • hadoop fs
      
    • [-appendToFile  ... ]
              [-cat [-ignoreCrc]  ...]
              [-chgrp [-R] GROUP PATH...]
              [-chmod [-R]  PATH...]
              [-chown [-R] [OWNER][:[GROUP]] PATH...]
              [-copyFromLocal [-f] [-p]  ... ]
              [-copyToLocal [-p] [-ignoreCrc] [-crc]  ... ]
              [-count [-q]  ...]
              [-cp [-f] [-p]  ... ]
              [-df [-h] [ ...]]
              [-du [-s] [-h]  ...]
              [-get [-p] [-ignoreCrc] [-crc]  ... ]
              [-getmerge [-nl]  ]
              [-help [cmd ...]]
              [-ls [-d] [-h] [-R] [ ...]]
              [-mkdir [-p]  ...]
              [-moveFromLocal  ... ]
              [-moveToLocal  ]
              [-mv  ... ]
              [-put [-f] [-p]  ... ]
              [-rm [-f] [-r|-R] [-skipTrash]  ...]
              [-rmdir [--ignore-fail-on-non-empty]  ...]
       ]]
              [-setrep [-R] [-w]   ...]
              [-stat [format]  ...]
              [-tail [-f] ]
              [-test -[defsz] ]
              [-text [-ignoreCrc]  ...]
      
  • 常用命令实操

    • 上传
      • -moveFromLocal:从本地剪切粘贴到HDFS
      • -copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去
      • -put:等同于copyFromLocal,生产环境更习惯用put
      • -appendToFile:追加一个文件到已经存在的文件末尾
    • 下载
      • -copyToLocal:从HDFS拷贝到本地
      • -get:等同于copyToLocal,生产环境更习惯用get
    • HDFS直接操作
      • -ls:显示目录信息
      • -cat:显示文件内容
      • -chgrg、-chmod、-chown:Linux文件系统中的用法一样,修改文件所属权限
      • -mkdir:创建路径
      • -cp:从HDFS的一个路径拷贝到HDFS的另一个路径
      • -mv:在HDFS目录中移动文件
      • -tail:显示一个文件的末尾1kb的数据
      • -rm:删除文件或文件夹
      • -rm -r:递归删除目录即目录里面的内容
      • -du:统计文件夹大小的信息
      • -setrep:设置HDFS中文件的副本数量

HDFS的API操作

  • 准备客户端环境

    • 拷贝hadoop-3.1.0到非中文路径
    • 配置HADOOP_HOME环境变量

    • 配置Path环境变量

    • 安装微软运行库

    • 在IDEA中创建一个Maven工程

      • 
            
                org.apache.hadoop
                hadoop-client
                3.1.3
            
            
                junit
                junit
                4.12
            
            
                org.slf4j
                slf4j-log4j12
                1.7.30
            
        
        
    • 在项目的src/main/resources目录下,新建一个文件,命名为"logfj.properties",在文件中填入

      • log4j.rootLogger=INFO, stdout  
        log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
        log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
        log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
        log4j.appender.logfile=org.apache.log4j.FileAppender  
        log4j.appender.logfile.File=target/spring.log  
        log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
        log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
        
    • 创建包名:com.lotuslaw

    • 创建HDFSClient类

      • public class HdfsClient {
        
            @Test
            public void testMkdirs() throws IOException, URISyntaxException, InterruptedException {
        
                // 1 获取文件系统
                Configuration configuration = new Configuration();
        
                // FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration);
                FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration,"atguigu");
        
                // 2 创建目录
                fs.mkdirs(new Path("/xiyou/huaguoshan/"));
        
                // 3 关闭资源
                fs.close();
            }
        }
        
  • HDFS的API案例实操

    • package com.lotuslaw;
      
      /**
       * @author: lotuslaw
       * @version: V1.0
       * @package: com.lotuslaw
       * @create: 2021-11-22 15:49
       * @description:
       */
      
      import org.apache.hadoop.conf.Configuration;
      import org.apache.hadoop.fs.*;
      import org.junit.After;
      import org.junit.Before;
      import org.junit.Test;
      
      import java.io.IOException;
      import java.net.URI;
      import java.net.URISyntaxException;
      import java.util.Arrays;
      
      /**
       * 客户段代码常用套路
       * 1、获取一个客户端代码
       * 2、执行相关的操作命令
       * 3、关闭资源
       * HDFS zookeeper
       */
      public class HdfsClient {
      
          private FileSystem fs;
      
          @Before
          public void init() throws URISyntaxException, IOException, InterruptedException {
              // 连接的集群nn地址
              URI uri = new URI("hdfs://hadoop102:8020");
              // 创建一个配置文件
              Configuration configuration = new Configuration();
              configuration.set("dfs.replication", "2");
              // 用户
              String user = "lotuslaw";
              // 获取到了客户端对象
              fs = FileSystem.get(uri, configuration, user);
          }
      
          @After
          public void close() throws IOException {
              // 关闭资源
              fs.close();
          }
      
          @Test
          public void testmkdir() throws URISyntaxException, IOException, InterruptedException {
      
              // 创建一个文件夹
      //        fs.mkdirs(new Path("/xiyou/huaguoshan1"));
          }
      
          // 上传
      
          /**
           * 参数优先级
           * hdfs-default.xml >> hdfs-site.xml >> 资源目录下的配置文件优先级 >> 代码里的配置
           */
          @Test
          public void testPut() throws IOException {
              // 参数一:表示删除元数据;参数二:是否覆盖;参数三:原数据路径;参数四:目的地路径
      //        fs.copyFromLocalFile(false, false, new Path("D:\\7-bigdata\\test_data\\孙悟空3.txt"), new Path("hdfs://hadoop102/xiyou/huaguoshan"));
          }
      
          // 文件下载
          @Test
          public void testGet() throws IOException {
              // 参数的解读:参数一:原文件是否删除;参数二:原文件路径HDFS;参数三:目标地址路径Win;参数四:是否开启本地校验,false开启
      //        fs.copyToLocalFile(false, new Path("hdfs://hadoop102/xiyou/huaguoshan/孙悟空.txt"), new Path("D:\\7-bigdata\\test_data\\孙悟空4.txt"), false);
          }
      
          // 删除
          @Test
          public void testRm() throws IOException {
              // 参数解释:参数1:要删除的路径;参数二:是否递归删除
      //        fs.delete(new Path("/xiyou/huaguoshan/孙悟空2.txt"), false);
      
              // 删除空目录
      //        fs.delete(new Path("/xiyou/huaguoshan1"), false);
      
              // 删除非空目录
      //        fs.delete(new Path("/xiyou/huaguoshan"), true);
          }
      
          // 文件的更名和移动
          @Test
          public void testmv() throws IOException {
              // 参数解读:参数1:原文件路径;参数2:目标文件路径
      //        fs.rename(new Path("/input/word.txt"), new Path("/input/lotuslaw.txt"));
      
              // 文件的移动和更名
      //        fs.rename(new Path("/input/lotuslaw.txt"), new Path("/lotuslaw2.txt"));
      
              // 目录的更名
      //        fs.rename(new Path("/xiyou"), new Path("/xiyou2"));
          }
      
          // 获取文件详细信息
          @Test
          public void fileDetail() throws IOException {
              // 获取文件信息
              RemoteIterator listFiles = fs.listFiles(new Path("/"), true);
      
              // 遍历文件
      //        while (listFiles.hasNext()){
      //            LocatedFileStatus fileStatus = listFiles.next();
      //            System.out.println("===========" + fileStatus.getPath() + "============");
      //            System.out.println(fileStatus.getPermission());
      //            System.out.println(fileStatus.getOwner());
      //            System.out.println(fileStatus.getGroup());
      //            System.out.println(fileStatus.getLen());
      //            System.out.println(fileStatus.getModificationTime());
      //            System.out.println(fileStatus.getReplication());
      //            System.out.println(fileStatus.getBlockSize());
      //            System.out.println(fileStatus.getPath().getName());
      //
      //            // 获取块信息
      //            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
      //
      //            System.out.println(Arrays.toString(blockLocations));
      //        }
          }
      
          // 判断是文件夹还是文件
          @Test
          public void testFile() throws IOException {
              FileStatus[] listStatus = fs.listStatus(new Path("/"));
              // 增强for循环
              for (FileStatus status: listStatus) {
                  if (status.isFile()){
                      System.out.println("文件" + status.getPath().getName());
                  } else {
                      System.out.println("目录" + status.getPath().getName());
                  }
              }
          }
      }
      
    • <?xml version="1.0" encoding="UTF-8"?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
      
      
          
              dfs.replication
              1
          
      
      

HDFS的读写流程(重点)

  • HDFS写数据流程

    • 剖析文件写入

    • 网络拓扑-节点距离计算
      • 在HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据
      • 节点距离:两个节点到达最近的共同祖先的距离总和

    • 机架感知(副本存储节点选择)

  • HDFS读数据流程

NameNode和SecondaryNameNode

  • NN和2NN工作机制

    • 首先,我们做个假设,如果NameNode的元数据存储在NameNode节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然效率过低。因此,元数据需要存放在内存中。但是如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的FsImage
    • 这样优惠带来新的问题,当在内存中的与元数据更新时,如果同时更新FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦NameNode节点断电,就会产生数据丢失。因此,引入Edits文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中。这样,一旦NameNode节点断电,可以通过FsImage和Edits的合并,合成元数据
    • 但是如果长时间添加数据到Edits中,会导致该文件数据过大,效率过低,而且一旦断电,恢复元数据需要的时间过长。因此,需要定期进行FsImage和Edits的合并,如果这个操作由NameNode的节点完成,又会效率过低,因此,引入一个新的节点SecondaryNameNode,专门用于FsImage和Edits的合并

  • FsImage和Edits解析

  • 查看oiv和oev命令

    • hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
      
    • hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml
      
    • hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
      
    • hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop-3.1.3/edits.xml
      
  • CheckPoint时间设置

    • 通常情况下,SecondaryNameNode每隔一小时执行一次

      • 
        
          dfs.namenode.checkpoint.period
          3600s
        
        
    • 一分钟检查一次操作次数,当操作次数达到一百万时,SecondaryNameNode执行一次

      • 
          dfs.namenode.checkpoint.txns
          1000000
        操作动作次数
        
        
        
          dfs.namenode.checkpoint.check.period
          60s
         1分钟检查一次操作次数
        
        

DataNode

  • DataNode工作机制

    • DN向NN汇报当前解读信息的时间间隔,默认6小时

      • 
        	dfs.blockreport.intervalMsec
        	21600000
        	Determines block reporting interval in milliseconds.
        
        
    • DN扫描自己节点快信息列表的时间,默认6小时

      • 
        	dfs.datanode.directoryscan.interval
        	21600s
        	Interval in seconds for Datanode to scan data directories and reconcile the difference between blocks in memory and on the disk.
        	Support multiple time unit suffix(case insensitive), as described
        	in dfs.heartbeat.interval.
        	
        
        
    • 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令。如果超过10分钟+30s没有收到某个DataNode的心跳,则认为该节点不可用

    • 集群运行中可以安全加入和退出一些机器

  • 数据完整性

    • DataNode在其文件创建后,周期性验证CheckSum

  • 掉线时限参数

    • 
          dfs.namenode.heartbeat.recheck-interval
          300000
      
      
      
          dfs.heartbeat.interval
          3