Yarn及MapReduce工作流程(总结版)

Yarn及MapReduce工作流程(总结版)

(未写出在hdfs上传和下载数据的流程,此流程请详见nn和2nn的爱恨情仇以及nn和dn的老大和小弟的故事)

Yarn工作流程:
在这里插入图片描述
​ 1.MR程序提交到客户端所在的节点,客户端向RM发出申请Application的请求

​ 2.RM同意,并返回提交资源的路径stag和application_id。

​ 3客户端向集群的hdfs提交job运行所需要的资源,提交之后会生成向集群提交数据的stag路径、生成job_id、FileInputFormat调用getSplites()获取切片规划,并序列化成二进制文件、含有job运行参数的job.xml、集群运行所需要的jar包。

​ 4.资源提交完毕之后,向RM提交执行MRAppMaster的请求。

​ 5.RM把客户端的请求变成Task,并放进容量资源调度器(hadoop默认的),等待节点认领。

​ 6.某个节点拿到Task之后,生成Contain容器,并运行MRAppmaster。

​ 7.下载hdfs上的资源到本地。

​ 8.根据在hdfs上下载的切片规划,MR向RM申请运行运行的切片等同数量的MapTask。

​ 9.RM把Task放容量资源调度器,等待指定的节点领取MapTask。

​ 10.节点领取到MapTask之后,生成contain,并执行MapTask;

MapTask阶段:
在这里插入图片描述
​ 11.MapTask会调用默认的TextInputFormat使用LineRecordReader一行行读取文件的数据。(read阶段)

​ 12.读取的数据经过map()之后,会被上下文对象context以kv键值对的形式写出会,并等待被Collector环形缓冲区(默认是100m)使用collect()收集。(map阶段)

​ 13.数据到了环形缓冲区之后,会选择一个分界点,kv数据会向右边存储,kv的元信息(包括索引、分区信息、keystart、valuestart)向左边存储,当达到环形缓冲区的百分之八十之后(默认是半分之八十),在剩下的20m中寻找一个新的分界点,存储的形式跟原来保持一致;存储完毕的80m会溢出落盘,在溢出之前会进行一次快速排序,保证数据在区内有序,如果有conbiner(),那么会进行区内的key合并,做完这些之后才进行落盘。如果写入环形缓冲区的速度大于溢出的速度,写入会等待一下。(collect阶段、spill(溢出)阶段)

​ 14.溢出完毕之后,会把本节点所有的溢出文件进行一次归并排序形成一个大的文件,如果有conbiner(),会进行一次节点内合并key。(meger(合并)阶段)

RedcueTask阶段:
在这里插入图片描述
​ 15.ReduceTask会主动copy自己负责的区的所有节点的数据,如果数据不大,会全部放在内存中,如果数据很大会溢写到磁盘里。(ReduceTask的数量最好跟分区数保持一致,如果分区数大于1,RedcueTask的数目小于分区数会报Exception,如果大于,多于的部分会生成空文件,如果就有一个ReduceTask那么就只会生成一个文件)。(copy阶段)

​ 16.ReduceTask会把数据进行归并排序。(meger和sort阶段)

​ 17.经过归并排序之后的数据计入reduce方法,之后数据会通过TextOutputFormat(hadoop默认的输出)的RecordWriter写到hdfs上面。OutputFormat可以自定义,详细内容如下(rduce阶段)。

OutputFormat阶段:

​ 18.可以选择自定义输出(其实就是按照需求,把数据存到存到的路径),具体的实现就是自定义类继承OutputFormat,覆写里面的getRecordWriter(),要求返回RecordWriter对象,所以又要自定义一个类继承RecordWirter类并覆写里面的write()和close(),其实就是需要输出流,根据需求输出到不同的位置即可,一下是具体的代码:

MyOutputFormat类:

public class MyOutputFormat extends FileOutputFormat<Text, NullWritable> {

    @Override
    public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException {
        LogRecordWriter logRecordWriter = new LogRecordWriter(job);
        return logRecordWriter;
    }
}

LogRecordWriter类:

public class LogRecordWriter extends RecordWriter<Text, NullWritable> {
    FileSystem fs = null;
    FSDataOutputStream out1 = null;
    FSDataOutputStream out2 = null;
    public LogRecordWriter(TaskAttemptContext job) throws IOException {
        //利用job对象获取配置文件对象
        Configuration configuration = job.getConfiguration();
        //获取FileSystem对象
        fs = FileSystem.get(configuration);
        //获取输出流
        out1 = fs.create(new Path("D://temp/log1"));
        out2 = fs.create(new Path("D://temp/log2"));

    }


    @Override
    public void write(Text key, NullWritable value) throws IOException, InterruptedException {
        if(key.toString().contains("atguigu")){
            out1.writeBytes(key.toString()+"\n");
        }else {
            out2.writeBytes(key.toString()+"\n");
        }
    }

    @Override
    public void close(TaskAttemptContext context) throws IOException, InterruptedException {
        //使用IO工具类IOUtils关闭流
        IOUtils.closeStream(out1);
        IOUtils.closeStream(out2);
    }
}



猜你喜欢

转载自blog.csdn.net/weixin_43363395/article/details/107599419