Hadoop2.76学习一

Hadoop的发展史

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evmweTEm-1682083127585)(Hadoop学习(一).assets/image-20220516205521689.png)]

Google

​ 爬取全球的网站,然后计算页面的PageRank

​ 要解决网站的问题:

​ a:这些网站怎么存放

​ b:这些网站应该怎么计算

​ 发布了三篇论文

​ a:GFS(Google File System)

​ b:MapReduce(数据计算方法)

​ c:BigTable:HBase

​ Doug cutting 花费了自己的两年业余时间,将论文实现了出来,这时候看到他儿子在牙牙学语时,抱着黄色小象,亲昵的叫 hadoop,他灵光一闪,就把这技术命名为 Hadoop,而且还用了黄色小象作为标示 Logo,不过,事实上的小象瘦瘦长长,不像 Logo 上呈现的那么圆胖。“我儿子现在 17 岁了,所以就把小象给我了,有活动时就带着小象出席,没活动时,小象就丢在家里放袜子的抽屉里。” Doug Cutting 大笑着说。
Hadoop(java)

HDFS

MapReduce

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IKLRQjlm-1682083127586)(Hadoop学习(一).assets/image-20220516210829470.png)]

Hadoop三大开源发行版本:Apache、Cloudera(CDH)、Hortonworks(HDP)。Apache版本最原始(最基础)的版本,对于入门学习最好。Cloudera在大型互联网企业中用的较多。Hortonworks文档较好。

Apache Hadoop

​ 官网地址:https://hadoop.apache.org/

​ 下载地址:https://hadoop.apache.org/release.html

Cloudera Hadoop

​ 官网地址:https://www.cloudera.com/downloads/cdh.html

​ 下载地址:https://docs.cloudera.com/documentation/enterprise/6/release-notes/topics/rg_cdh_6_download.html

​ 1)2008年成立的Cloudera是最早将Hadoop商用的公司,为合作伙伴提供Hadoop的商用解决方案,主要是包括支持、咨询服务、培训。

​ 2)2009年Hadoop的创始人Doug Cutting也加盟Cloudera公司。Cloudera产品主要为CDH,Cloudera Manager,Cloudera Support

​ 3)CDH是Cloudera的Hadoop发行版,完全开源,比Apache Hadoop在兼容性,安全性,稳定性上有所增强。Cloudera的标价为每年每个节点10000美元

​ 4)Cloudera Manager是集群的软件分发及管理监控平台,可以在几个小时内部署好一个Hadoop集群,并对集群的节点及服务进行实时监控。

​ 5)Cloudera的标价为每年每个节点4000美元。Cloudera开发并贡献了可实时处理大数据的Impala项目。

Hortonworks Hadoop

​ 官网地址:https://www.clouderacn.cn/products/hdp.html

​ 下载地址:https://www.cloudera.com/downloads/hdp.html

​ 1)2011年成立的Hortonworks是雅虎与硅谷风投公司Benchmark Capital合资组建。

​ 2)公司成立之初就吸纳了大约25名至30名专门研究Hadoop的雅虎工程师,上述工程师均在2005年开始协助雅虎开发Hadoop,贡献了Hadoop80%的代码。

​ 3)雅虎工程副总裁、雅虎Hadoop开发团队负责人Eric Baldeschwieler出任Hortonworks的首席执行官。

​ 4)Hortonworks的主打产品是Hortonworks Data Platform(HDP),也同样是100%开源的产品,HDP除常见的项目外还包括了Ambari,一款开源的安装和管理系统。

​ 5)HCatalog,一个元数据管理系统,HCatalog现已集成到Facebook开源的Hive中。Hortonworks的Stinger开创性的极大的优化了Hive项目。Hortonworks为入门提供了一个非常好的,易于使用的沙盒。

​ 6)Hortonworks开发了很多增强特性并提交至核心主干,这使得Apache Hadoop能够在包括Window Server和Windows Azure在内的microsoft Windows平台上本地运行。定价以集群为基础,每10个节点每年为12500美元。

2018年10月,均为开源平台的Cloudera与Hortonworks公司宣布他们以52亿美元的价格合并。

​ 官方网站:https://www.cloudera.com/

​ Cloudera 官方文档: https://www.cloudera.com/documentation/enterprise/latest.html

​ 两家公司称合并后公司将拥有2500客户、7.2亿美元收入和5亿美元现金,且没有债务,宣布了它们所谓了相对平等的合并。

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bkp5ERA0-1682083127586)(Hadoop学习(一).assets/image-20220516213522994.png)]

​ 两大开源大数据平台Cloudera与Hortonworks宣布合并,合并后的企业定位为企业数据云提供商,推出了ClouderaDataPlatform(CDP),可以跨AWS、Azure、Google等主要公有云架构进行数据管理。2020年6月,Cloudera发布CDP私有云,将本地部署环境无缝连接至公有云。

​ CDP的版本号延续了之前CDH的版本号,从7.0开始延续

​ 那么CDP对比之前的Cloudera Enterprise Data Hub(CDH企业版)与HDPEnterprise Plus(HDP企业版)到底在组件上发生了哪些变化呢?

​ 由于HDP在国内市场上的市场占有量很小,大部分公司都是采用CDH,所以对于HDP带来的一些东西,使用CDH的用户和开发人员会比较陌生,下面带大家详细的了解一下CDP中的组件一些变化,也方便同学们为在2023年以及之后的学习做好准备。

​ CDP、CDH、HDP中都包含的部分

Apache Hadoop(HDFS/YARN/MR)

Apache HBase

Apache Hive

Apache Oozie

Apache Spark

Apache Sqoop

Apache Zookeeper

Apache Parquet

Apache Phoenix(*CDH中需要额外安装)

最关键的一点:CDP的组件代码在github上找不到,是不再开源了,CDP7以后就没有社区版了。

Hadoop 1.x —> 3.x

官网:https://hadoop.apache.org/

注意:课程中的hadoop版本以CDH版本为准,稳定且主流,目前国内主流的是2.x,如果面试的时候说你用的是3.x可能会有些不一样。。。。并且2.x的变化都不大

Hadoop Common:基础型功能

Hadoop Distributed File System (HDFS™):一种分布式文件系统,可提供对应用程序数据的高吞吐量访问。负责存放数据

Hadoop YARN:作业调度和集群资源管理的框架。负责资源的调配

Hadoop MapReduce:基于 YARN 的系统,用于并行处理大型数据集。大数据的计算框架

Hadoop框架透明地为应⽤提供可靠性和数据移动。它实现了名为MapReduce的编程范式:应⽤程序被分割成许多⼩部分,⽽每个部分都能在集群中的任意节点上执⾏或重新执⾏。此外,Hadoop还提供了分布式⽂件系统,⽤以存储所有计算节点的数据,这为整个集群带来了⾮常⾼的带宽。MapReduce和分布式⽂件系统的设计,使得整个框架能够⾃动处理节点故障。它使应⽤程序与成千上万的独⽴计算的电脑和PB级的数据。

一句话简述:Hadoop是一个适合海量数据的分布式存储和分布式计算的平台。(面试必问!!!!)

国内现在大数据的行情

​ 1)大数据的薪资属于同行业最高的

​ 2)相对来讲这个技术比较稳定,Hadoop只是大数据的一员或者说是基石,大数据开发环境已经稳定。

说到这的时候,带同学画一下目前主流的框架图,熟悉主题学习框架和功能,画图总结上面的概念

分布式文件系统架构 DFS

一、名词科普

Apache基金会
是专门为支持开源软件项目而办的一个非盈利性组织
服务器(节点): 企业里任务和程序基本都是运行在服务器上。服务器内存和cpu以及硬盘等资源和性能远高于pc机
可以理解为我们的一台笔记本/台式机
在这里可以认为是我们的一台虚拟机
后面学习中,我们会把一台服务器称为一个节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1UARJUl-1682083127587)(Hadoop学习(一).assets/image-20220516220501671.png)]

机架: 一个公司里,会有很多服务器。尤其是hadoop集群大到上千台服务器搭建成集群
负责存放服务器的架子
可以理解为鞋架(_)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vPU9v4bR-1682083127587)(Hadoop学习(一).assets/image-20220516220536829.png)]

二、分布式文件系统(从这开始,下面都是属于Hadoop中的原理)

1、FS File System

​ 文件系统是基于硬盘之上的文件管理的工具

​ 我们用户操作文件系统可以和硬盘进行解耦

2、DFS Distributed File System

​ 分布式文件系统

​ 将我们的数据存放在多台电脑上存储

​ 分布式文件系统有很多,HDFS(Hadoop Distributed FileSyetem)是Hadoop自带的分布式文件系统

​ HDFS是mapreduce计算的基础

三、文件切分的思想(引出分而治之的思想 第一个核心思想)

​ a. 文件存放在一个磁盘上效率肯定是最低的

​ 读取效率低

​ 如果文件特别大会超出单机的存储范围

​ b. 字节数组

​ 文件在磁盘真实存储文件的抽象概念

​ 数组可以进行拆分和组装,源文件不会收到影响

​ c. 切分数据

​ 对字节数组进行切分

​ d. 拼接数据

​ 按照数组的偏移量将数据连接到一起,将字节数组连接到一起

​ e. 偏移量

​ 当前数据在数组中的相对位置,可以理解为下标

​ 数组都有对应的索引,可以快速定位数据

​ f. 数据存储的原理:

​ 不管文件的大小,所有的文件都是由字节数组构成

​ 如果我们要切分文件,就是将一个字节数组分成多份

​ 我们将切分后的数据拼接到一起,数据还可以继续使用

​ 我们需要根据数据的偏移量将他们重新拼接到一起

四、Block拆分标准

数据块Block

​ a. 是磁盘进行数据 读/写的最小单位,数据被切分后的一个整体被称之为块
​ b. 在Hadoop 1默认大小为64M,在Hadoop 2及其之后默认大小为128M块,这么大是为了最小化寻址开销
​ c. 同一个文件中,每个数据块的大小要一致除了最后一个节点外
​ 不同文件中,块的大小可以不一致
​ 文件大小不同可以设置不同的块的数量
HDFS中小于一个块的大小的文件不会占据整个块的空间
​ d. 真实情况下,会根据文件大小和集群节点的数量综合考虑块的大小
​ e. 数据块的个数=Ceil(文件大小/每个块的大小)

拆分的数据块需要等大(面试题:为什么hadoop的block块大小是固定等大的?)

​ a. 数据计算的时候简化问题的复杂度(否则进行分布式算法设计的时候会因为数据量不一很难设计)
​ b. 数据拉取的时候时间相对一致
​ c. 通过偏移量就知道这个块的位置
​ d. 相同文件分成的数据块大小应该相等

注意事项

​ a. 只要有任意一个块丢失,整个数据文件被损坏
​ b. HDFS中一旦文件被存储,数据不允许被修改
​ 修改会影响偏移量

修改会导致数据倾斜(单节点数据量过多)

​ a. 修改数据会导致蝴蝶效应最终导致数据倾斜
​ b. 但是可以被追加(一般不推荐)
​ 追加设置需要手动打开
​ c. 一般HDFS存储的都是历史数据.所以将来Map Reduce都用来进行离线数据的处理
​ d. 块的大小一旦文件上传之后就不允许被修改 128M-512M(一般企业在搭建的时候就已经固定了)

五、Block数据安全

​ a. 只要有任意一个块丢失,整个数据文件被损坏
​ b. 肯定要对存储数据做备份
​ c. HDFS是直接对原始数据进行备份的,这样能保证恢复效率和读取效率
​ d. 备份的数据肯定不能存放在一个节点上,使用数据的时候可以就近获取数据
​ f. 备份的数量要小于等于节点的数量
​ g. 每个数据块默认会有三个副本,相同副本是不会存放在同一个节点上
​ h. 副本的数量可以变更
​ 可能近期数据被分析的可能性很大,副本数可以多设置几个
​ 后期数据很少被分析,可以减少副本数

六、Block的管理效率

需要专门给节点进行分工

  • 存储 DataNode 实际存储数据的节点
  • 记录 NameNode
  • 日志 Secondary NameNode

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pulARG6z-1682083127588)(Hadoop学习(一).assets/image-20220516225946842.png)]

java模拟切分文件(统计每个班级的人数)

切分文件

package com.shujia.wyh.java_moni_hadoop;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;

/**
 * 前提:假设每一行数据是1M大小,文件大小是100M,将来会产生8个block块
 */
public class SplitFileToBlocks {
    public static void main(String[] args) throws Exception {
        //1、将文件读取进来
        //使用IO流,因为students.txt是一个文本文件,所以使用字符缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("bigdata23-hadoop/data/students.txt"));
        //定义一个序号,表示往哪个文件写(这里的文件其实模拟的就是一个一个的block块)
        int index = 0;
        //创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("bigdata23-hadoop/data/blocks/block-" + index));

        //定义一个变量记录行数
        int rowNumber = 0;
        //使用ArrayList集合存储已经读取到的数据,因为List相关集合具有索引的概念,方便统计读行数的变化
        ArrayList<String> list = new ArrayList<>();

        //定义一个变量表示每次开始写入的位置
        int startIndex = 0;

        //开始编写生成block块的逻辑代码
        //为了模拟1.1的溢出,大概是140M的时候,开始生成一个block块
        String line = null;
        while ((line = br.readLine()) != null) {
            //读到了一行,行数+1
            rowNumber++;
            //将读取到数据写到集合中
            list.add(line);
            //当读取到140条数据的时候写到block文件中
            if (rowNumber == 140) {
                startIndex = 128 * index;
                for (int i = startIndex; i <= startIndex + 127; i++) {
                    bw.write(list.get(i));
                    bw.newLine();
                    bw.flush();
                }
                rowNumber = 12;
                index++;
                bw = new BufferedWriter(new FileWriter("bigdata23-hadoop/data/blocks/block-" + index));
            }
        }

        //将剩下的数据也写到一个block文件中
        for (int i = list.size() - rowNumber; i < list.size(); i++) {
            bw.write(list.get(i));
            bw.newLine();
            bw.flush();
        }


        //释放资源
        bw.close();
        br.close();
    }
}

map任务

package com.shujia.wyh.java_moni_hadoop;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//模拟hadoop中每一个block块都会产生一个map任务,注意,这里仅仅是模拟,和真正的hadoop产生map任务的过程有所差距
//真正的hadoop中map任务生成会将倒数第二个与最后一个block块组合起来看一看大小,如果组合大小是小于128*1.1的,就产生一个map任务,
//否则一个block块对应一个map任务
//对于我们这里模拟就一个block块产生一个map任务,暂时不考虑128*1.1的溢出
public class Map {
    public static void main(String[] args) {
        //由于是多个block块,就应该使用多个线程来进行处理
        //使用线程池
        ExecutorService pool = Executors.newFixedThreadPool(8);
        //将bigdata23-hadoop/data/blocks进行封装
        File file = new File("bigdata23-hadoop/data/blocks");
        //获取该目录下的所有文件
        File[] files = file.listFiles();
        //定义一个变量,表示读取到的是第几个block块
        int index = 0;

        for (File file1 : files) {
            pool.submit(new MyMap(file1,index));
            index++;
        }

        pool.shutdown();
    }
}

map任务执行

package com.shujia.wyh.java_moni_hadoop;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MyMap implements Runnable {
    private File file;
    private int index;
    BufferedReader br;
    BufferedWriter bw;


    public MyMap(File file, int index) {
        this.file = file;
        this.index = index;
    }

    @Override
    public void run() {
        /**
         * 统计每个block块中班级个数
         */
        try {
            br = new BufferedReader(new FileReader(file.getAbsolutePath()));
            HashMap<String, Integer> map = new HashMap<>();
            String line = null;
            while ((line = br.readLine()) != null) {
                String clazz = line.split(",")[4];
                //向集合添加元素
                if (!map.containsKey(clazz)) {
                    map.put(clazz, 1);
                } else {
                    map.put(clazz, map.get(clazz) + 1);
                }
            }

            //统计后将集合中的结果写入到文件中
            bw = new BufferedWriter(new FileWriter("bigdata23-hadoop/data/mapouts/part-m-" + index));
            //遍历集合,将每一个map任务计算的结果写入到文件中
            Set<Map.Entry<String, Integer>> entries = map.entrySet();
            for (Map.Entry<String, Integer> entry : entries) {
                String clazz = entry.getKey();
                Integer number = entry.getValue();
                bw.write(clazz+":"+number);
                bw.newLine();
                bw.flush();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

reduce任务

package com.shujia.wyh.java_moni_hadoop;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Reduce {
    public static void main(String[] args) throws Exception {
        //创建一个Map集合统计每个班级的人数
        HashMap<String, Integer> map = new HashMap<>();

        //将mapouts目录封装成File对象
        File file = new File("bigdata23-hadoop/data/mapouts");
        File[] files = file.listFiles();
        BufferedReader br = null;
        if(files!=null){
            for (File file1 : files) {
                br = new BufferedReader(new FileReader(file1.getAbsolutePath()));
                String line = null;
                while ((line = br.readLine()) != null) {
                    String clazz = line.split(":")[0];
                    Integer number = Integer.valueOf(line.split(":")[1]);
                    if (!map.containsKey(clazz)) {
                        map.put(clazz, number);
                    } else {
                        map.put(clazz, number + map.get(clazz));
                    }
                }
            }
        }


        //创建一个字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("bigdata23-hadoop/data/output/part-r-00000"));

        //遍历集合写入到最终结果文件
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            String clazz = entry.getKey();
            Integer numbers = entry.getValue();
            bw.write(clazz + "\t" + numbers);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
        if (br != null) {
            br.close();
        }

    }
}

项目一 搭建项目之Hadoop集群搭建(完全分布式版本)

一、准备工作

  • 三台虚拟机:master、node1、node2

  • 时间同步

    ntpdate ntp.aliyun.com
    
  • 调整时区

    cp  /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime
    
  • jdk1.8(三台都要配置

    java -version
    
  • 修改主机名

    三台分别执行 vim /etc/hostname 并将内容指定为对应的主机名
    
  • 关闭防火墙:systemctl stop firewalld (三台机器都要检查) (第二步)

    • 查看防火墙状态:systemctl status firewalld (第一步)
    • 取消防火墙自启:systemctl disable firewalld (第三步)
  • 静态IP配置(三台机器都要检查)

    • 直接使用图形化界面配置(不推荐)

    • 手动编辑配置文件进行配置

      1、编辑网络配置文件
      vim /etc/sysconfig/network-scripts/ifcfg-ens33
      
      TYPE=Ethernet
      BOOTPROTO=static
      HWADDR=00:0C:29:E2:B8:F2
      NAME=ens33
      DEVICE=ens33
      ONBOOT=yes
      IPADDR=192.168.190.100
      GATEWAY=192.168.190.2
      NETMASK=255.255.255.0
      DNS1=192.168.190.2
      DNS2=223.6.6.6
      
      需要修改:HWADDR(mac地址,centos7不需要手动指定mac地址)
      		IPADDR(根据自己的网段,自定义IP地址)
      		GATEWAY(根据自己的网段填写对应的网关地址)
      
      2、关闭NetworkManager,并取消开机自启
      systemctl stop NetworkManager
      systemctl disable NetworkManager
      
      3、(如果上面的网络做了操作)重启网络服务
      systemctl restart network
      
  • 免密登录

    # 1、生成密钥
    ssh-keygen -t rsa
    # 2、配置免密登录
    ssh-copy-id master的ip地址
    ssh-copy-id node1的ip地址
    ssh-copy-id node2的IP地址
    # 3、测试免密登录
    ssh node1
    
  • 配置好映射文件:/etc/hosts

    192.168.190.100 master
    192.168.190.101 node1
    192.168.190.102 node2
    

二、搭建Hadoop集群

NameNode:接受客户端的读/写服务,收集 DataNode 汇报的 Block 列表信息

DataNode:真实数据存储的地方(block)

SecondaryNameNode:做持久化的时候用到

进程master(主)node1(从)node2(从)
NameNode
SecondaryNameNode
ResourceManager
DataNode
NodeManager

2.1 完全分布式搭建

1、上传安装包并解压
# 使用xftp上传压缩包至master的/usr/local/soft/packages/
cd /urs/local/soft/packages/
# 解压
tar -zxvf hadoop-2.7.6.tar.gz -C /usr/local/soft/
2、配置环境变量
vim /etc/profile

JAVA_HOME=/usr/local/soft/jdk1.8.0_171
HADOOP_HOME=/usr/local/soft/hadoop-2.7.6
export PATH=$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

# 重新加载环境变量
source /etc/profile
3、修改Hadoop配置文件
  • cd /usr/local/soft/hadoop-2.7.6/etc/hadoop/

  • core-site.xml

    fs.defaultFS: 默认文件系统的名称。其方案和权限决定文件系统实现的URI。uri的方案确定命名文件系统实现类的配置属性(fs.scheme.impl)。uri的权限用于确定文件系统的主机、端口等。

    hadoop.tmp.dir:是 hadoop文件系统依赖的基本配置,很多配置路径都依赖它,它的默认位置是在 /tmp/{$user}下面,注意这是个临时目录!!!

    因此,它的持久化配置很重要的! 如果选择默认,一旦因为断电等外在因素影响,/tmp/{$user}下的所有东西都会丢失。

    fs.trash.interval:启用垃圾箱配置,dfs命令删除的文件不会立即从HDFS中删除。相反,HDFS将其移动到垃圾目录(每个用户在/user/<username>/.Trash下都有自己的垃圾目录)。只要文件保留在垃圾箱中,文件可以快速恢复。

        <property>
            <name>fs.defaultFS</name>
            <value>hdfs://master:9000</value>
        </property>
    
        <property>
            <name>hadoop.tmp.dir</name>
            <value>/usr/local/soft/hadoop-2.7.6/tmp</value>
        </property>
    
        <property>
            <name>fs.trash.interval</name>
            <value>1440</value>
        </property>
    
  • hadoop-env.sh

    export JAVA_HOME=/usr/local/soft/jdk1.8.0_171
    

    image.png

  • hdfs-site.xml

  • dfs.replication:每个datanode上只能存放一个副本。我这里就2个datanode

    dfs.permissions:如果为“true”,则在HDFS中启用权限检查。如果为“false”,则关闭权限检查,但所有其他行为保持不变。从一个参数值切换到另一个参数值不会更改文件或目录的模式、所有者或组。

        <property>
            <name>dfs.replication</name>
            <value>1</value>
        </property>
    
        <property>
            <name>dfs.permissions</name>
            <value>false</value>
        </property>
    
  • mapred-site.xml.template

  • mapreduce.framework.name:用于执行MapReduce作业的运行时框架。

    mapreduce.jobhistory.address:Hadoop自带了一个历史服务器,可以通过历史服务器查看已经运行完的Mapreduce作业记录,比如用了多少个Map、用了多少个Reduce、作业提交时间、作业启动时间、作业完成时间等信息。默认情况下,Hadoop历史服务器是没有启动的,我们可以通过*mr-jobhistory-daemon.sh start historyserver命令来启动Hadoop历史服务器。我们可以通过Hadoop jar的命令来实现我们的程序jar包的运行,关于运行的日志,我们一般都需要通过启动一个服务来进行查看,就是我们的JobHistoryServer,我们可以启动一个进程,专门用于查看我们的任务提交的日志。mapreduce.jobhistory.address和mapreduce.jobhistory.webapp.address默认的值分别是0.0.0.0:10020和0.0.0.0:19888

    # 1、重命名文件
    cp mapred-site.xml.template mapred-site.xml
    # 2、修改
        <property>
            <name>mapreduce.framework.name</name>
            <value>yarn</value>
        </property>
    
        <property>  
            <name>mapreduce.jobhistory.address</name>  
            <value>master:10020</value>  
        </property>  
    
        <property>  
            <name>mapreduce.jobhistory.webapp.address</name>  
            <value>master:19888</value>  
        </property> 
    
  • slaves

  • 从节点的信息

    node1
    node2
    
  • yarn-site.xml

  • yarn.resourcemanager.hostname:指定yarn主节点

yarn.nodemanager.aux-services:NodeManager上运行的附属服务。需配置成mapreduce_shuffle,才可运行MapReduce程序。默认值:“”

yarn.log-aggregation-enable:yarn日志聚合功能开关

yarn.log-aggregation.retain-seconds:日志保留时限,默认7天

    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>master</value>
    </property>

    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>

    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>

    <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>604800</value>
    </property>
4、分发Hadoop到node1、node2
cd /usr/local/soft/
scp -r hadoop-2.7.6/ node1:`pwd`
scp -r hadoop-2.7.6/ node2:`pwd`
5、格式化namenode(第一次搭建完之后启动之前需要执行)(在主节点中执行!!!)
hdfs namenode -format

image.png

6、启动Hadoop集群
start-all.sh
7、检查master、node1、node2上的进程
  • master:

    [root@master soft]# jps
    2597 NameNode
    2793 SecondaryNameNode
    2953 ResourceManager
    3215 Jps
    
  • node1:

    [root@node1 jdk1.8.0_171]# jps
    11361 DataNode
    11459 NodeManager
    11559 Jps
    
  • node2:

    [root@node2 ~]# jps
    11384 DataNode
    11482 NodeManager
    11582 Jps
    
8、访问HDFS的WEB界面
http://master:50070

image.png

9、访问YARN的WEB界面
http://master:8088

image.png

Hadoop中的常见的shell命令

1、如何将linux本地的数据上传到HDFS中呢?
hadoop fs -put 本地的文件 HDFS中的目录
hdfs dfs -put 本地的文件 HDFS中的目录

2、如何创建HDFS中的文件夹呢?
需求:想创建/shujia/bigdata17
hadoop fs -mkdir /shujia/bigdata17
hdfs dfs -mkdir /shujia/bigdata17

3、查看当前HDFS目录下的文件和文件夹
hadoop fs -ls /shujia/bigdata17
hdfs dfs -ls /shujia/bigdata17

4、将HDFS的文件下载到Linux本地中
hadoop fs -get HDFS中的文件目录 本地要存放文件的目录
hdfs dfs -get HDFS中的文件目录 本地要存放文件的目录

5、删除命令(如果垃圾回收站大小小于被删除文件的大小,直接被删除,不经过回收站)
hadoop fs -rm ....  # 仅删除文件
hadoop fs -rmr .... # 删除文件夹


6、移动文件
hadoop fs -mv 目标文件  目的地路径

7、HDFS内部复制文件
hadoop fs -cp [-p] ... ... # 如果想复制文件夹,加上-p参数

强制格式化集群(遇到问题的简单暴力的方法)

1、停止正在运行的集群

​ stop-all.sh

2、删除所有节点hadoop根目录中的tmp文件夹

3、在主节点(master)中hadoop的根目录中的bin目录下,重新格式化HDFS

./hdfs namenode -format

4、启动集群

​ start-all.sh

2.2 进程理解

HDFS相关(NN,DN,SSN)
NameNode(NN)

功能:

​ 1、接受客户端的读/写服务

​ 因为NameNode知道数据文件与DataNode的对应关系

​ 2、保存文件的时候会保存文件的元数据信息

​ a. 文件的归属

​ b. 文件的权限

​ c. 文件的大小,时间

​ d. Block信息,但是block的位置信息不会持久化,需要每次开启集群的时候DN向NN汇报。(带同学们画图讲解,引出这4个点)

​ 3、收集Block的位置信息

​ 3.1 系统启动

​ a. NN关机的时候是不会存储任何的Block与DataNode的映射信息的

​ b. DN启动的时候会自动将自己节点上存储的Block信息汇报给NN

​ c. NN接收请求之后会重新生成映射关系

​ File ----> Block

​ Block—> DN

​ d. 如果数据块的副本数小于设置数,那么NN会将这个副本拷贝到其他节点

​ 3.2 集群运行中

​ a. NN与DN保持心跳机制,三秒钟发送一次

​ b. 如果客户端需要读取或者上传数据的时候,NN可以知道DN的健康情况

​ c. 可以让客户端读取存活的DN节点

​ d. 如果NN与DN三秒没有心跳则认为DN出现异常,此时不会让新的数据写到这个异常的DN中,客户端访问的时候不提供异常DN节点地址

​ e. 如果超过十分钟没有心跳,那么NN会将当前DN节点存储的数据转移到其他的节点

​ 4、NameNode为了效率,将所有的操作都在内存中进行

​ a. 执行速度快

​ b. NameNode不会和磁盘进行任何的数据交换

​ 但是会存在两个问题:

​ 1)数据的持久化

​ 2)数据保存在内存中,断电丢失

DataNode(DN)

1、存放的是文件的数据信息(block块的信息),以及验证文件完整性的校验信息(.meta)

2、数据会存放在硬盘上

​ a. 1m=1条元数据

​ b. 1G=1条元数据

​ c. NameNode非常排斥存储小文件(能存,但是不推荐!!面试必问)

​ 一般小文件在存储之前需要进行压缩,合并成大文件等操作

3、汇报

​ 1)启动时

​ 汇报之前会验证Block文件是否被损坏

​ 向NN汇报当前DN上block的信息

​ 2)运行中

​ 向NN保持心跳机制

4、当客户端读写数据的时候,首先会先去NN查询file与block与DN的映射,然后客户端直接与DN建立连接,然后读写数据

SecondaryNameNode(SNN)

1、传统的内存持久化方案

​ 1)日志机制

​ a. 做任何操作之前先记录日志

​ b. 在数据改变之前先记录对应的日志,当NN停止的时候

​ c. 当我下次启动的时候,只需要重新按照以前的日志“重做一遍”即可

缺点:

​ a. log日志文件的大小不可控,随着时间的发展,集群启动的时间会越来越长

​ b. 有可能日志中存在大量的无效日志

优点:

​ a. 绝对不会丢失数据

​ 2)拍摄快照

​ a. 我们可以将内存中的数据写出到硬盘上(序列化)

​ b. 启动时还可以将硬盘上的数据写回到内存中(反序列化)

缺点:

​ a. 关机时间过长

​ b. 如果是异常关机,数据还在内存中,没法写入到硬盘

​ c. 如果写出的频率过高,导致内存使用效率低

优点:

​ 启动时间较短

2、SNN的解决方案(面试题)

​ 1)解决思路

​ a. 让日志大小可控(每64M)

​ b. 快照需要定时保存(每隔1h)

​ c. 日志+快照

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mtBUYkBI-1682083127590)(Hadoop学习(一).assets/1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xrFK4Yu9-1682083127590)(Hadoop学习(一).assets/2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n821YIhs-1682083127590)(Hadoop学习(一).assets/3.png)]

​ 2)解决方案

​ a. 当我们启动一个集群的时候,会产生4个文件 …/name/current/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s310o416-1682083127591)(Hadoop学习(一).assets/image-20220521005240506.png)]

​ b. 我们每次操作都会记录日志–>edits-inprogress- edits_00000001,随着时间的推移,日志文件会越来越大-当达到阈值的时候(64M或3600秒),会生成新的日志文件,edits_inprogress-000000001 -->edits_0000001,创建新的日志文件 edits_inprogress-0000000016。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKmciv5f-1682083127591)(Hadoop学习(一).assets/image-20220523212030016.png)]

注意:如果学生不理解,再带着学生画图走一遍流程!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rAirizQJ-1682083127591)(Hadoop学习(一).assets/image-20220524144600294.png)]

2.3 安全模式

安全模式是 HDFS 的一种工作状态,处于安全模式的状态下,只向客户端提供文件的只读视图,不接受对命名空间的修改;同时 NameNode 节点也不会进行数据块的复制或者删除,
NameNode 启动时,
1)首先将镜像文件( fsimage )载入内存,并执行编辑日志( edits )中的各项操作。
2)一旦在内存中成功建立文件系统元数据的映射,则创建一个新的 fsimage 文件和一个空的编辑日志。
3)NameNode 开始监听 RPC 和 Http 请求。
4)此时 NameNode 处于安全模式,只接受客户端的读请求。

​ 5)处于这个状态是为了保护数据的安全所以只能被客户端访问读取数据

# 对安全模式的理解
# 1.工作流程
	a.启动 NameNode,NameNode 加载 fsimage 到内存,对内存数据执行 edits log 日 志中的事务操作。
	b.文件系统元数据内存镜像加载完毕,进行 fsimage 和 edits log 日志的合并,并创 建新的 fsimage 文件和一个空的 edits log 日志文件。
	c.NameNode 等待 DataNode 上传 block 列表信息,直到副本数满足最小副本条件。
	d.当满足了最小副本条件,再过 30 秒,NameNode 就会退出安全模式。最小副本条件指 整个文件系统中有 99.9%的 block 达到了最小副本数(默认值是 1,可设置)
# 在 NameNode 安全模式(safemode)
	对文件系统元数据进行只读操作
	当文件的所有 block 信息具备的情况下,对文件进行只读操作
	不允许进行文件修改(写,删除或重命名文件)
# 2.注意事项
	a.NameNode 不会持久化 block 位置信息;DataNode 保存各自存储的 block 列表信息。 正常操作时,NameNode 在内存中有一个 blocks 位置的映射信息(所有文件的所有文 件块的位置映射信息)。
	b.NameNode 在安全模式,NameNode 需要给 DataNode 时间来上传 block 列表信息到 NameNode。如果 NameNode 不等待 DataNode 上传这些信息的话,则会在 DataNode 之间进行 block 的复制,而这在大多数情况下都是非必须的(因为只需要等待 DataNode 上传就行了),还会造成资源浪费。
	c.在安全模式 NameNode 不会要求 DataNode 复制或删除 block。
	d.新格式化的 HDFS 不进入安全模式,因为 DataNode 压根就没有 block。
# 4.命令操作
# 通过命令查看 namenode 是否处于安全模式:
hdfs dfsadmin -safemode get
Safe mode is ON HDFS 的前端 webUI 页面也可以查看 NameNode 是否处于安全模式。 有时候我们希望等待安全模式退出,之后进行文件的读写操作,尤其是在脚本中,此时:
`hdfs dfsadmin -safemode wait`
# your read or write command goes here 管理员有权在任何时间让 namenode 进入或退出安全模式。进入安全模式:
`hdfs dfsadmin -safemode enter`
Safe mode is ON 这 样 做 可 以 让 namenode 一 直 处 于 安 全 模 式 , 也 可 以 设 置 `dfs.namenode.safemode.threshold-pct` 为 1 做到这一点。 离开安全模式:
`hdfs dfsadmin -safemode leave`
Safe mode is OFF

系统中的数据块的位置并不是由 NameNode 维护的,而是以块列表的形式存储在 DataNode 中。
[root@node01 ~]# rm -rf /var/yjx/hadoop/full/dfs/name/current/*
[root@node01 ~]# scp -r
root@node02:/var/yjx/hadoop/full/dfs/namesecondary/current/*
/var/yjx/hadoop/full/dfs/name/current

安全模式下
a. 安全模式下,各个 DataNode 会向 NameNode 发送自身的数据块列表
b. 当 NameNode 有足够的数据块信息后,便在 30 秒后退出安全模式
c. NameNode 发现数据节点过少会启动数据块复制过程
如果 NN 收集的 Block 信息没有达到最少副本数,就会将缺失的副本 , 从有的 DN 上拷贝到其他 DN
a. dfs.replication.min=2
b. 但是默认最低副本数为 1
c. 在拷贝的过程中系统还是处于安全模式
安全模式相关命令
hadoop dfsadmin -safemode leave 强制 NameNode 退出安全模式
hadoop dfsadmin -safemode enter 进入安全模式
hadoop dfsadmin -safemode get 查看安全模式状态
hadoop dfsadmin -safemode wait 等待一直到安全模式结束

2.4 HDFS的权限

HDFS对权限的控制

​ a. 只能防止好人做错事

​ b. 不能防止坏人做坏事

但是告诉你是谁,他就认为你是谁!!

2.5 机架感知

机架感知是为了保证副本在集群中的安全性
我们需要将block块下放在不同的DN节点上,节点也需要一定的考量
可靠性,可用性,带宽消耗
第一个节点:
集群内部(优先考虑和客户端相同的节点作为第一个节点)
集群外部(选择资源丰富且不繁忙的节点作为第一个节点)
第二个节点:
第二个节点选择与第一个节点不同机架的其他节点
第三个节点:
与第二个相同机架相同的其他节点
第N个节点:
与前面节点不重复的其他节点

第一种模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JhyzU1XP-1682083127592)(Hadoop学习(一).assets/image-20220523215731288.png)]

第二种模式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0vUt92jh-1682083127592)(Hadoop学习(一).assets/image-20220523215755428.png)]

2.6 HDFS的读写流程(重点!)

写数据

写数据就是将客户端上的数据上传到HDFS

2.6.1 宏观过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H9MZjiNQ-1682083127592)(Hadoop学习(一).assets/image-20220523220340057.png)]

1.客户端向HDFS发送写数据请求

hdfs dfs -put students.txt /shujia/

2. Filesystem通过rpc调用namenode的put方法

a. nn首先检查是否有足够的空间权限等条件创建这个文件,或者这个路径是否已经存在,权限

b. 有:NN会针对这个文件创建一个空的Entry对象,并返回成功状态给DFS

c. 没有:直接抛出对应的异常,给予客户端错误提示信息

3.如果DFS接收到成功的状态,会创建一个FSDataOutputStream的对象给客户端使用

4.客户端要向nn询问第一个Block存放的位置

​ NN通过机架感知策略 (node1 node 2 node3)

5.需要将客户端和DN节点创建连接

pipeline(管道)

客户端 和 node1 创建连接 socket
node1 和 node2 创建连接 socket
node2 和 Node3 创建连接 socket

6.客户端按照文件块切分数据,但是按照packet发送数据
默认一个packet大小为64K,Block128M为2048个packet

7.客户端通过pipeline管道开始使用FDSOutputStream对象将数据输出

    1. 客户端首先将一个 packet 发送给 node1, 同时给予 node1 一个 ack 状态
    2. node1接受数据后会将数据继续传递给 node2, 同时给予 node2 一个 ack 状态
    3. node2接受数据后会将数据继续传递给 node3, 同时给予 node3 一个 ack 状态
    4. node3将这个 packet 接受完成后,会响应这个 ack 给 node2 为 true
    5. node2会响应给 node1 , 同理 node1 响应给客户端

8.客户端接收到成功的状态 , 就认为某个 packet 发送成功了,直到当前块所有的 packet 都发送完成

​ 1. 如果客户端接收到最后一个 pakcet 的成功状态 , 说明当前 block 传输完成,管道就会被撤销

​ 2. 客户端会将这个消息传递给 NN , NN 确认传输完成

​ 1. NN会将 block 的信息记录到 Entry, 客户端会继续向 NN 询问第二个块的存储位置 , 依次类推

​ block1 (node1 node2 node3)

​ block2 (node1 node3 node6)

​ …

​ blockn(node1 node4 node6)

  1. 当所有的 block 传输完成后, NN 在 Entry 中存储所有的 File 与 Block 与 DN 的映射关系关闭
FsDataOutPutStream
2.6.2 微观过程(如何保证package发送的时候不出错呢?)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tQ3LMANt-1682083127593)(Hadoop学习(一).assets/image-20220523222153267.png)]

1.客户端首先从自己的硬盘中以流的形式将自己的数据读取到缓存中
2.然后将缓存中的数据以chunk(512B)和checksum(4B)的方式放入到packet(64k)

1. chunk:checksum=128:1
2. checksum:在数据处理和数据通信领域中,用于校验目的的一组数据项的和
3. Packet中的数据分为两类,一类是实际数据包,另一类是 header 包。
4. 一个 Packet 数据包的组成结构(分两类,一类是实际的数据包,另一类是header包。)

一个数据包的组成结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gIfhbyXB-1682083127593)(Hadoop学习(一).assets/image-20220523222659558.png)]

参数理解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zp3oDi4N-1682083127593)(Hadoop学习(一).assets/image-20220523223115417.png)]

3.(默认生成的快,发送的慢)当packet满的时候添加到dataqueue
4.datastreamer开始从dataqueue队列上读取一个packet,通过FDSDataOPS发送到Poepleline
在取出的时候,也会将 packet 加入到 ackQueue, 典型的生产者消费者模式

​ 客户端发送一个 Packet 数据包以后开始接收 ack ,会有一个用来接收 ack 的 ResponseProcessor 进
程,如果收到成功的 ack

1. 如果某一个 packet 的 ack 为 true, 那么就从 ackqueue 删除掉这个 packet
2. 如果某一个 packet 的 ack 为 false, 将 ackqueue 中所有的 packet 重新挂载到 发送队列 , 重新发送

最终DFS保存的数据格式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vPXtqQoZ-1682083127594)(Hadoop学习(一).assets/image-20220523224116381.png)]

读数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jf9focWj-1682083127594)(Hadoop学习(一).assets/image-20220523224203820.png)]

1.首先客户端发送请求到 DFS ,申请读取某一个文件
2.DFS 去 NN 查找这个文件的信息 ( 权限 , 文件是否存在 )
如果文件不存在,抛出指定的错误
如果文件存在,返回成功状态
3.DFS 创建 FSDataInputStream 对象,客户端通过这个对象读取数据
4.客户端获取文件第一个 Block 信息 , 返回 DN1 DN2 DN8
5.客户端直接就近原则选择 DN1 对应的数据即可
6.依次类推读取其他块的信息,直到最后一个块 , 将 Block 合并成一个文件
7.关闭 FSDataInputStream

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

混分吴老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值