Hadoop学习笔记

大数据简介

在这里插入图片描述
在这里插入图片描述

Hadoop伪分布式安装

  1. 安装JDK
  2. 关闭防火墙
  3. 修改主机名 - 在Hadoop节点的主机名中不允许出现-或者_
    vim /etc/sysconfig/network
    修改HOSTNAME的属性值,例如
    HOSTNAME=hadoop01
    保存退出,重新生效
    source /etc/sysconfig/network
  4. 将主机名和IP进行映射
    vim /etc/hosts
    添加IP 主机名,例如
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    10.9.162.133 hadoop01
  5. 重启
    reboot
  6. 配置免密登录
    ssh-keygen
    ssh-copy-id root@hadoop01
    云主机密码:tarena2017Up;
    ssh hadoop01
    如果不需要,那么输入logout
  7. 进入software
    cd /home/software/
  8. 下载Hadoop的安装包
    wget http://bj-yzjd.ufile.cn-north-02.ucloud.cn/hadoop-2.7.1_64bit.tar.gz
  9. 解压
    tar -xvf hadoop-2.7.1_64bit.tar.gz
  10. 进入配置目录
    cd hadooop-2.7.1/cd etc/hadoop/
  11. 编辑
    vim hadoop-env.sh
    修改
    export JAVA_HOME=/home/presoftware/jdk1.8
    export HADOOP_CONF_DIR=/home/software/hadoop-2.7.1/etc/hadoop
    保存退出,重新生效
    source hadoop-env.sh
  12. 编辑
    vim core-site.xml
    添加

    fs.defaultFS
    hdfs://hadoop01:9000


    hadoop.tmp.dir
    /home/software/hadoop-2.7.1/tmp
  13. 编辑
    vim hdfs-site.xml
    添加

    dfs.replication
    1
  14. 复制
    cp mapred-site.xml.template mapred-site.xml
    编辑
    vim mapred-site.xml
    添加

    mapreduce.framework.name
    yarn
  15. 编辑
    vim yarn-site.xml
    添加

    yarn.resourcemanager.hostname
    hadoop01


    yarn.nodemanager.aux-services
    mapreduce_shuffle
  16. 编辑
    vim slaves
    添加当前云主机的主机名
  17. 配置环境变量
    vim /etc/profile
    添加
    export HADOOP_HOME=/home/software/hadoop-2.7.1
    export PATH= P A T H : PATH: PATH:HADOOP_HOME/bin:$HADOOP_HOME/sbin
    保存退出,重新生效
    source /etc/profile
  18. 格式化NameNode
    hadoop namenode -format
    如果日志中出现Storage directory /home/software/hadoop-2.7.1/tmp/dfs/name has been successfully formatted.表示格式化成功
    ***** 如果格式化失败,那么改完错误之后,检查/home/software/hadoop-2.7.1目录下是否存在tmp目录。如果有,那么删掉tmp之后再重新格式化
  19. 启动Hadoop
    start-all.sh

通过jps查看
Jps
NameNode
DataNode
SecondaryNameNode
ResourceManager
NodeManager

如果出现Name or Service not known或者是Unknown Host,那么检查hosts文件是否配置正确

HDFS

在这里插入图片描述

使用代码连接hdfs,并上传下载文件

package cn.tedu.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;

import java.io.*;
import java.net.URI;

public class HDFSDemo {

    // 下载文件
    @Test
    public void get() throws IOException {
        // 创建环境参数
        Configuration conf = new Configuration();
        // 连接HDFS
        FileSystem fs = FileSystem.get(URI.create("hdfs://10.9.162.133:9000"), conf);
        // 指定文件 - 返回输入流
        InputStream in = fs.open(new Path("/a.xml"));
        // 创建输出流
        FileOutputStream out = new FileOutputStream("E:\\test.xml");
        // 读取数据,将读取的数据写出
        // byte[] bs = new byte[1024];
        // int len;
        // while ((len = in.read(bs)) != -1)
        //     out.write(bs, 0, len);
        IOUtils.copyBytes(in, out, conf);
        // 关流
        in.close();
        out.close();
    }

    // 上传文件
    @Test
    public void put() throws IOException, InterruptedException {
        // 创建环境参数
        Configuration conf = new Configuration();
        // 凡是可以放到配置文件中的属性都可以放在这个参数中
        // conf中的配置优先于配置文件中的配置
        // 指定Block是64M大小
        conf.set("dfs.blocksize", "67108864");
        // 指定副本数量
        conf.set("dfs.replication", "1");
        // 连接HDFS
        FileSystem fs = FileSystem.get(
                URI.create("hdfs://10.9.162.133:9000"), conf, "root");
        // 指定存放位置 - 返回输出流
        OutputStream out = fs.create(new Path("/b.xml"));
        // 指定要上传的文件
        FileInputStream in = new FileInputStream("D:\\test.xml");
        // 上传文件
        IOUtils.copyBytes(in, out, conf);
        // 关流
        in.close();
        out.close();
    }

    // 删除文件
    @Test
    public void delete() throws IOException, InterruptedException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
                URI.create("hdfs://10.9.162.133:9000"), conf, "root");
        // 删除文件
        // 第二个参数表示是否递归
        fs.delete(new Path("/a"), true);
    }

}

流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MapReduce

在这里插入图片描述

执行过程概括

应该是每一行数据调用一次mapper,每一个键调用一次reducer方法
在这里插入图片描述

在reduce刚开始的时候,会将相同的键对应的值放到一块去–分组;这里是如何区分是不是一组的呢,其实是利用的实体封装对象的compareTo()方法进行的比较,如果返回值的为0,就表示这两个对象是同一个;他的另一个作用是进行排序,如果返回的是this-obj,就表示升序排列,如果返回的是obj-this,就表示降序排列。
在这里插入图片描述

数据本地化策略

其实就是把处理数据的TaskTrack和存储数据的datanode部署到同一个节点上
在这里插入图片描述

job执行流程

在这里插入图片描述

在这里插入图片描述

Shuffle

在这里插入图片描述

InputFormat输入格式

在这里插入图片描述
在这里插入图片描述

自定义输入格式

在这里插入图片描述

package cn.tedu.authinput;

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.util.LineReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;

// 自定义输入格式:getSplis计算切片   createRecordReader:获取数据流来读取数据,但是FileInputFormat这个实现类已经
//覆盖了getSplis方法,所以我们只需要写 createRecordReader方法
//这里应该有两个方法:
// 泛型表示读取出来的数据类型
public class AuthInputFormat extends FileInputFormat<Text, Text> {
    @Override
    public RecordReader<Text, Text> createRecordReader(InputSplit split, TaskAttemptContext context) {
        return new AuthReader();
    }
}

class AuthReader extends RecordReader<Text, Text> {

    private static final byte[] blank = new Text(" ").getBytes();

    private LineReader reader;
    private Text key;
    private Text value;
    private float len;
    private float pos = 0;

    // 在初始化的时候被调用一次
    // 这个方法的目的就是为了获取一个真正用于读取数据的流
    @Override
    public void initialize(InputSplit split, TaskAttemptContext context) throws IOException {
        FileSplit fileSplit = (FileSplit) split;
        // 获取要读取的切片对应的路径
        Path path = fileSplit.getPath();
        // 获取切片大小
        len = fileSplit.getLength();
        // 连接HDFS
        FileSystem fs = FileSystem.get(
                URI.create(path.toString()), context.getConfiguration());
        // 指定要读取的文件
        // 获取到输入流用于读取文件
        // 输入流是一个字节流,但是原始文件是字符文件
        // 考虑将字节流转化为字符流,最好能够按行读取
        InputStream in = fs.open(path);
        reader = new LineReader(in);
    }

    // 判断是否有下一个键值对要传递到map方法中
    // 如果读取到了数据,那么说明还有数据要处理,那么就返回true
    // 如果没有读取到数据,那么说明数据已经处理完,那么就返回false
    @Override
    public boolean nextKeyValue() throws IOException {
        key = new Text();
        value = new Text();
        Text tmp = new Text();

        // 会将读取到的一行数据放到传入的tmp中
        // 返回值表示读取到的一行的字节个数
        if (reader.readLine(tmp) <= 0) return false;
        key.set(tmp.toString());
        pos += tmp.getLength();

        if (reader.readLine(tmp) <= 0) return false;
        value.set(tmp.toString());
        value.append(blank, 0, blank.length);
        pos += tmp.getLength();

        if (reader.readLine(tmp) <= 0) return false;
        byte[] data = tmp.getBytes();
        value.append(data, 0, data.length);
        pos += tmp.getLength();

        return true;
    }

    // 获取当前要处理的键
    @Override
    public Text getCurrentKey() {
        return key;
    }

    // 获取当前要处理的值
    @Override
    public Text getCurrentValue() {
        return value;
    }

    // 获取执行进度
    @Override
    public float getProgress() {
        return pos / len;
    }

    @Override
    public void close() throws IOException {
        if (reader != null) {
            reader.close();
        }
    }
}

在这里插入图片描述

多源输入

同时处理多个文件
在这里插入图片描述
在这里插入图片描述

切片过程中保证数据完整性的策略

在这里插入图片描述
解释:基本上一个block对应着一个切片,那么一个block的默认大小是128M,但是maptask在处理数据的时候都是按行处理的,这就导致可能一行数据处理到一半就到128m了,就会导致数据的不完整性,如下图:
在这里插入图片描述

输出格式

在这里插入图片描述
在这里插入图片描述

小文件

在这里插入图片描述

数据倾斜

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

推测执行机制

在这里插入图片描述

稳定排序与非稳定排序

冒泡排序是属于稳定排序,选择排序是非稳定排序
冒泡排序:从第一位开始,相邻两位互相比较,如果位置错误则交换位置,这样经过一轮的比较,最大的就排到了最后。然后比较除最后一位的其他数字,重复之前的逻辑。
选择排序:第一位和剩余所有数字相互比较,如果位置错误则交换位置。然后第二位,第三位…
稳定与非稳定的判断依据是:去除已经排好的元素之后,如果剩余元素的相对位置没有发生变化,那么这就是一个稳定排序,否则就是非稳定排序。

Hadoop完全分布式的搭建

完全分布式结构图

在这里插入图片描述

安装步骤

  1. 三台云主机需要安装JDK和Zookeeper
  2. 三台云主机需要关闭防火墙
  3. 修改三台云主机的主机名
    vim /etc/sysconfig/network
    修改HOSTNAME属性
    统一要求,第一台云主机改为hadoop01,第二台云主机改为hadoop02,第三台云主机改为hadoop03
    改完之后,保存退出,重新生效
    source /etc/sysconfig/network
  4. 三台云主机做IP映射
    vim /etc/hosts
    添加IP 主机名
    例如
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    10.9.12.131 hadoop01
    10.9.23.140 hadoop02
    10.9.133.238 hadoop03
    正常情况下,三台云主机改完之后的内容配置应该一模一样
    改完之后,保存退出
  5. 三台云主机重启
    reboot
  6. 三台云主机之间需要相互免密,每个云主机上都执行一遍
    ssh-keygen
    ssh-copy-id root@hadoop01
    ssh-copy-id root@hadoop02
    ssh-copy-id root@hadoop03
    云主机密码:tarena2017Up;
    ssh hadoop01 如果不需要输入密码,logout
    ssh hadoop02 如果不需要输入密码,logout
    ssh hadoop03 如果不需要输入密码,logout
  7. 三台云主机开启Zookeeper
    cd /home/software/zookeeper-3.4.8/bin
    sh zkServer.sh start
    sh zkServer.sh status
  8. 需要将第一台云主机上的伪分布式保留下来
    cd /home/software/
    mv hadoop-2.7.1 hadoop-alone
  9. 下载完全分布式安装包
    wget http://bj-yzjd.ufile.cn-north-02.ucloud.cn/hadoop-dist.tar.gz
  10. 解压
    tar -xvf hadoop-dist.tar.gz
  11. 三台云主机配置环境变量
    vim /etc/profile
    在文件末尾添加
    export HADOOP_HOME=/home/software/hadoop-2.7.1
    export PATH= P A T H : PATH: PATH:HADOOP_HOME/bin:$HADOOP_HOME/sbin
    改完之后,保存退出,重新生效
    source /etc/profile
  12. 在第一台云主机上远程拷贝
    scp -r hadoop-2.7.1 root@hadoop02:/home/software/
    scp -r hadoop-2.7.1 root@hadoop03:/home/software/
  13. 在第一台云主机上格式化Zookeeper - 这一步实际上是在Zookeeper上注册节点
    hdfs zkfc -formatZK
    如果出现Successfully created /hadoop-ha/ns in ZK.表示格式化成功
  14. 三台节点启动JournalNode
    hadoop-daemon.sh start journalnode
  15. 在第一台云主机上格式化NameNode
    hadoop namenode -format
    如果出现Storage directory /home/software/hadoop-2.7.1/tmp/hdfs/name has been successfully formatted.表示格式化成功
  16. 在第一台云主机上启动NameNode
    hadoop-daemon.sh start namenode
  17. 在第二台节点上格式化NameNode
    hdfs namenode -bootstrapStandby
    如果出现Storage directory /home/software/hadoop-2.7.1/tmp/hdfs/name has been successfully formatted.表示格式化成功
  18. 在第二台云主机上启动NameNode
    hadoop-daemon.sh start namenode
  19. 三台云主机启动DataNode
    hadoop-daemon.sh start datanode
  20. 在第一台和第二台云主机上启动DFSFailOverController
    hadoop-daemon.sh start zkfc
  21. 在第三台云主机上启动YARN
    start-yarn.sh
  22. 在第一台云主机上启动ResourceManager
    yarn-daemon.sh start resourcemanager

通过jps查看
第一台云主机上出现8个进程
Jps
NameNode
DataNode
JournalNode
DFSZKFailoverController
ResourceManager
NodeManager
QuorumPeerMain
第二台云主机上出现7个进程
Jps
NameNode
DataNode
JournalNode
DFSZKFailoverController
NodeManager
QuorumPeerMain
第三台云主机上出现6个进程
Jps
DataNode
JournalNode
ResourceManager
NodeManager
QuorumPeerMain

出现问题

  1. 如果出现Name or Service not known或者是Unknown host,那么检查hosts文件是否配置正确
  2. 如果出现Command not found,那么检查环境变量是否配置正确
  3. 如果在执行hdfs zkfc -formatZK出现了Hadoop HA is not available/enable,那么这个问题无法解决,这是系统兼容性问题 - 重装系统
  4. 如果在执行hdfs zkfc -formatZK出现IllegalArgument,那么检查命令是否书写正确
  5. 如果jps之后少了QuorumPeerMain,那么检查Zookeeper是否启动成功
  6. 如果少了NameNode/DataNode/JournalNode/DFSZKFailoverController,通过hadoop-daemon.sh start namenode/datanode/journalnode/zkfc来启动,例如hadoop-daemon.sh start journalnode
  7. 如果少了ResourceManager/NodeManager,那么通过yarn-daemon.sh start resourcemanager/nodemanager来启动,例如yarn-daemon.sh start nodemanager
  8. 如果格式化NameNode失败,那么检查完错误之后,需要删除/home/software/hadoop-2.7.1/tmp再重新格式化
  9. 如果启动过程中,出现running as processing 进程号,那么可以先kill -9 进程号,再重新启动这个进程
  10. 后续启动Hadoop完全分布式之前,需要先启动Zookeeper,然后再启动Hadoop

YARN

概述

在这里插入图片描述

job执行流程

在这里插入图片描述

注意问题

在这里插入图片描述

流程图

在这里插入图片描述

面试题

搭建Haddoop集群,应该如何选购云主机?
云主机的类型:内存型 高IO型 大磁盘型 计算型 CPU密集型

在这里插入图片描述
解释:这个问题实际上是在考察对Hadoop各个节点的理解,Namenode里边因为需要内存存储了大量的文件的元数据,所以选择内存型。DataNode上需要大量读取、存储block,所以选择高IO型。而且DataNode还会有数据的本地化策略,会将处理任务的TaskTracker保存到上边,所以选择计算型或者是CPU密集型。journalNode因为需要考虑消息的传递,所以选择io型,或者是内存型。ResourceManager

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值