04-hadoop基础

1.大数据概论

1.1大数据的概念

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

1.2大数据的业务分析流程

  • 产品人员提需求
  • 数据部门搭建数据平台、分析数据指标
  • 数据可视化

1.3大数据的应用场景

  • 零售
  • 物流仓库
  • 旅游

2.Hadoop

2.1Hadoop概述

2.1.1Hadoop的优势

  1. 高可靠性:Hadoop底层维护多个数据副本,防止某个节点宕机而产生数据流失
  2. 高扩展性:在集群间分配任务数据,可方便的拓展数以千计的节点
  3. 高效性:在mapreduce的思想下,Hadoop并行工作
  4. 高容错性:能将失败的任务重新分配

2.1.2Hadoop1版本和2版本的区别

1版本中的mapreduce既要处理计算,又要管理资源的调度,耦合性非常大,新增了yarn之后,mapreduce只负责计算

2.2Hadoop的安装

  1. 安装JDK
    1.1新建一个虚拟机,从已安装的jdk中输入命令
scp -r /usr/lcoal/jdk1.8.0_192
scp -r /etc/profile
scp -r /etc/hosts
  1. 关闭防火墙
sytemctl stop firewalld.service
sytemctl disable firewalld.service
  1. 重写source文件
source /etc/profile 
  1. 配置免密登录
//所有会话
ssh-keygen -t rsa
//所有会话连点三次回车
ssh-copy-id bigdata1
123456
ssh-copy-id bigdata2
ssh-copy-id bigdata3
ssh-copy-id bigdata4
ssh-copy-id bigdata5
  1. 配置核心文件
put 路径 文件名

6 分发到其他的主机上

scp -r /usr/local/hadoop-2.8.4 bigdata1:/usr/local
  1. 配置Hadoop环境变量
scp -r /etc/profile bigdata1:/etc/profile 
export  HADOOP_HOME=/usr/local/hadoop-2.8.4
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
  1. 检测Hadoop是否安装配置成功
Hadoop
  1. 格式化
//首先启动小弟的journalnode
hadoop-daemon.sh start journalnode
//在其中一个大哥里面输入
hdfs namenode -format 
hdfs zkfc -formatZK
//第二台也要格式化
hdfs namenode -format 
//看看log中是否有successfully
  1. 启动大哥的namenode
hadoop-daemon.sh start namenode//在所有的大哥上都要执行
hadoop-daemon.sh start zkfc //启动注册active
  1. 检验bigdata4:50070
    出现一个可视化界面
  2. 启动DataNode
//每一个zk上启动一个,都可以看到一个节点上线
hadoop-daemon.sh start datanode
  1. 启动资源调度
start-yarn.sh
  1. 检查是否是动态ip,导致节点无法上线
vi /etc/sysconfig/network-scripts/ifcfg-ens33
  1. 配置一键启动命令
//cat hadoop-env.sh 在usr/local/hadoop-2.8.4/etc/hadoop下面
export JAVA_HOME=/usr/local/jdk1.8.0_192
  1. 启动和停止命令
start-dfs.sh
stop-dfs.sh

2.4Hadoop三大组成

2.4.1HDFS

2.4.1.1hdfs的组成
  1. 图解
  2. 在这里插入图片描述
  3. namenode管理hdfs的命名空间、配置副本的策略、管理数据块的映射信息、处理客户端的读写请求
  4. datanode就是slaves,执行namenode下达的命令,负责存储实际的数据块、执行读写操作
  5. client客户端负责文件切分,切分成一个个block上传、与namnode交互获得文件的位置信息、与datanode交互读写数据、用一些命令管理hadfs增删改查
  6. secondarynamenode辅助namenode分担工作量
2.4.1.2hdfs读写文件
  1. hdfs写文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEGKzwwv-1570520487404)(CF83288EF7974F219B2E1884A90C7C3A)]
  • client创建一个distractedfilesystem向namenode请求上传数据
  • namenode响应可以上传数据
  • client请求上传第一个block的位置
  • 返回datanode1\datanode2\datanode3用这三个节点存储
  • fsoutputStream请求建立传输通道
  • 应答成功
  • 传输数据
  • 传输成功
  • 关闭流

2.hdfs读文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gebEuJzl-1570520487405)(4F45C2FDAF4E4260A6F3C511E9523453)]

  • 客户端打开分布式文件系统请求下载文件
  • namenode返回目标文件的元数据信息
  • 客户端打开fsinputstream请求在datanode1读取数据block1
  • 传数据
  • 客户端打开fsinputstream请求在datanode2读取数据block2
  • 传数据
  • 关流
2.4.1.3hdfs的namenode和secondarynamenode
  1. nn 和 2nn 工作机制
  • fsimage备份元数据信息,edits文件当元数据更新时在后面追加
  • 一旦namenode断电后可以通过fsimage和edits的合并得到元数据
  • 为了解决edits文件过大,需要定期合并,如果让namenode来做的话效率过低,所以引入了2nn
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7vEy5dNf-1570520487407)(F1DFB936D41A40B48D99DBCB04A992C0)]
  • namenode内存128g每个block占150byte
  • 启动namenode创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
  • 客户端传来元数据的更新请求
  • namenode记录操作日志,更新滚动日志
  • 当edits文件过大,或者checkpoint 时间到了之后,nm向2nm发送checkpoint请求
  • 2nm执行checkpoint将fsimage和edits拷贝到奥2nm
  • 加载到内存进行合并,生成fsimge.checkpoint
  • 拷贝到nm重命名
2.4.1.4hdfs的datanode

在这里插入图片描述

  • datanode1启动后向nm注册
  • 注册成功
  • datanode1每个周期向nm汇报所有块信息
  • datanode2每三秒钟发送一次心跳
  • 返回带有nm的指令
  • 超过十分钟没有心跳,就会认为该节点不可用

2.4.2mapreduce

2.4.2.1核心思想

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OypPdtCF-1570520487408)(349DC42AF44147B4B4280FC4CB63A705)]

  • map阶段读数据,一个分区对应一个maptask,将数据按行读入,
  • 以空格划分
  • 形成键值对
  • 通过不同的首字母划分成两个分区
  • reduce阶段
  • 将统计单词个数
  • 输出到文件
2.4.2.2序列化
  1. 定义
  • 将对象转换成字节序列以便于存到磁盘(持久化)和网络传输
  • 反序列化:将字节序列转换为内存中的对象
  1. 代码演示
package com.iweb.test;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class Sort {
static class SoMapper extends Mapper<LongWritable,Text, Flowbeen,Text>{

        Flowbeen k= new Flowbeen();
        Text v =new Text();
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String [] split = value.toString().split("\t");
        long sum_up = Long.parseLong(split [split.length-3]);
        long sum_down =  Long.parseLong(split[split.length-2]);
        k.set(sum_up,sum_down);
        v.set(split[1]);

        context.write(k,v);
    }
}
static class SoReduce extends Reducer<Flowbeen,Text,Text,Flowbeen>{

    protected void reduce(Flowbeen key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
        for (Text text:values
             ) {
            context.write(text,key);
        }


    }
}

    public static void main(String[] args) throws Exception{
        Configuration conf =new  Configuration();
        Job job =Job.getInstance(conf);
        Path src =null;
        Path dst =null;
        if(args.length==2){
            src =new Path(args[0]);
            dst = new Path(args [1]);
        }else {
            src =new Path("E:\\test\\sort\\in");
            dst =new Path("E:\\test\\sort\\out");
            conf.set("mapreduce.job.jar","F:\\workSpace\\java\\sort\\target\\sort-1.0-SNAPSHOT-jar-with-dependencies.jar");
        }
        FileSystem fs = FileSystem.get(conf);
        if (fs.exists(dst)){
            fs.delete(dst,true);
        }
        job.setMapperClass(SoMapper.class);
        job.setReducerClass(SoReduce.class);
        job.setOutputKeyClass(Flowbeen.class);
        job.setOutputValueClass(Text.class);
        FileInputFormat.addInputPath(job,src);
        FileOutputFormat.setOutputPath(job,dst);
        System.exit(job.waitForCompletion(true)?0:1);
    }
}

//bean
package com.iweb.test;


import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class Flowbeen implements Writable, WritableComparable<Flowbeen> {
    //1	13736230513	192.196.100.1	www.atguigu.com	2481	24681	200
   private long up;
   private long down;
   private long sum;

    public Flowbeen() {
        super();
    }

    public Flowbeen(long up, long down) {
        super();
        this.up = up;
        this.down = down;
        this.sum = up+down;
    }

    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeLong(up);
        dataOutput.writeLong(down);
        dataOutput.writeLong(sum);
    }

    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.up = dataInput.readLong();
        this.down = dataInput.readLong();
        this.sum = dataInput.readLong();
    }

    @Override
    public String toString() {
        return up +
                "\t" + down +
                "\t" + sum ;
    }

    public long getUp() {
        return up;
    }

    public void setUp(long up) {
        this.up = up;
    }

    public long getDown() {
        return down;
    }

    public void setDown(long down) {
        this.down = down;
    }

    public long getSum() {
        return sum;
    }

    public void setSum(long sum) {
        this.sum = sum;
    }


    public void set(long upFlow, long downFlow) {
        this.up = upFlow;
        this.down = downFlow;
        this.sum = upFlow + downFlow;
    }
    @Override
    public int compareTo(Flowbeen o) {
        int result;
        if(sum>o.getSum()){
            result = -1;
        }else if (sum<o.getSum()){
            result = 1;
        }else {
            result =0;
        }

        return  result;
    }
}
2.4.2.3框架原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pJFzqDZC-1570520487412)(D3BDB508B13841A58EF3655C49B63AA8)]

  1. Fileinputformat源码解析
  • 首先程序获得文件的存储目录
  • 遍历所有像切片的文件
    – 遍历第一个文件
    –返回文件的大小
    – 计算文件的切片:默认情况下 切片大小等于blocksize
    – 每次切分都要判断剩下的是否是块的1.1倍决定是否在分一块
    – 将切片信息写到有一个切片的规划文件中
    – 整个切片的方法在getsplit中完成
    – inputformat只记录了切片的元数据信息,起始位置,长度
  • 提交切片规划文件到yarn上,yarn的app master就可以通过切片规划文件开启maptask的个数
  1. CombineTextInputFormat
  • 框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
  1. FileInputFormat实现类
  • TextIuputFormat、KeyValueTextIuputFormat、NLineinputFormat、CombineTextInputFormat、自定义inputformat
2.4.2.4shuffle机制

在这里插入图片描述

  • Shuffle的大致流程为:Maptask会不断收集我们的map()方法输出的kv对,放到内存缓冲区中,当缓冲区达到饱和的时候(默认占比为0.8)就会溢出到磁盘中,如果map的输出结果很多,则会有多个溢出文件,多个溢出文件会被合并成一个大的溢出文件,在文件溢出、合并的过程中,都要调用partitoner进行分组和针对key进行排序(默认是按照Key的hash值对Partitoner个数取模),之后reducetask根据自己的分区号,去各个maptask机器上取相应的结果分区数据,reducetask会将这些文件再进行合并(归并排序)。

合并成大文件后,shuffle的过程也就结束了,后面进入reducetask的逻辑运算过程(从文件中取出每一个键值对的Group,调用UDF函数(用户自定义的方法))

2.4.2.5数据输出

在这里插入图片描述

  • 自定义
//自定义一个OutputFormat类
public class FilterOutputFormat extends FileOutputFormat<Text, NullWritable>{

	@Override
	public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext job)			throws IOException, InterruptedException {

		// 创建一个RecordWriter
		return new FilterRecordWriter(job);
	}
}
//编写RecordWriter
public class FilterRecordWriter extends RecordWriter<Text, NullWritable> {

	FSDataOutputStream atguiguOut = null;
	FSDataOutputStream otherOut = null;
	public FilterRecordWriter(TaskAttemptContext job) {

		// 1 获取文件系统
		FileSystem fs;

		try {
			fs = FileSystem.get(job.getConfiguration());

			// 2 创建输出文件路径
			Path atguiguPath = new Path("e:/atguigu.log");
			Path otherPath = new Path("e:/other.log");

			// 3 创建输出流
			atguiguOut = fs.create(atguiguPath);
			otherOut = fs.create(otherPath);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void write(Text key, NullWritable value) throws IOException, InterruptedException {

		// 判断是否包含“atguigu”输出到不同文件
		if (key.toString().contains("atguigu")) {
			atguiguOut.write(key.toString().getBytes());
		} else {
			otherOut.write(key.toString().getBytes());
		}
	}

	@Override
	public void close(TaskAttemptContext context) throws IOException, InterruptedException {

		// 关闭资源
IOUtils.closeStream(atguiguOut);
		IOUtils.closeStream(otherOut);	}
}
2.4.2.6join
  • Map Join:Map Join适用于一张表十分小、一张表很大的场景。
    (1)在Mapper的setup阶段,将文件读取到缓存集合中。
    (2)在驱动函数中加载缓存。
    // 缓存普通文件到Task运行节点。
    job.addCacheFile(new URI(“file://e:/cache/pd.txt”));
  • Reduce Join:Map端的主要工作:为来自不同表或文件的key/value对,打标签以区别不同来源的记录。然后用连接字段作为key,其余部分和新加的标志作为value,最后 进行输出。Reduce端的主要工作:在R educe端以连接字段作为key的分组已经完成,我们只需要在一个分组当中将那些来源于不同文件的记录(在Map阶段已经打标志)分开,最后进行台并就k了。

2.4.3yarn

  • 运行机制
    在这里插入图片描述
    (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会清理工作状态。作业的信息会被作业历史服务器存储以备之后用户核查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值