Hadoopのアセンブリ(MR-糸HDFS)

MapReduceは..分散コンピューティングプログラムは、2つのフェーズに分けて三つのプロセスの合計を低減さマップのコアフレームワークのHadoopベースのデータ解析と計算です。

AppMaster:状態のプログラムのスケジュールと調整のプロセス全体の責任

MapTask:全体的なデータ処理フローマップ段階の責任

ReduceTaskは:全体のデータストリーム処理段階に責任を削減します

地図段階:(複数のタスクにタスクを担当します)

Map的编程规范:

1.用户自定义的Mapper继承自己的父类Mapper

2.Mapper的输入数据是KV对的形式(可自定义)

3.Mapper中的业务逻辑写在map方法中

4.Mapper的输出数据是KV对的形式(可自定义)

5.map()方法对每一个<k,v>调用一次

舞台を削減:(後処理タスク分解要約の結果の責任)

Reducer:

1.用户自定义Reducer要继承Reducer

2.Reducer的输入类型要对应Mapper的输出类型,也是kv

3.Reducer的业务逻辑写在reduce()方法中

4.ReduceTask进程对每一组相同的<k,v>组调用一次reduce()方法

ドライバ段:

相当于yarn集群的客户端,用于提交我们整个程序到yarn集群,提交的是封装了Map Reduce程序相关运行参数的job对象

MapReduceの処理:

1.对文件进行切片,提前想好块的大小如何分配
2.启动相应数量的 maptask 进程
3.调用 FileInputFormat 中的 RecordReader,读一行数据并封装为 k1v1
4.调用自定义的 map 函数,并将 k1v1 传给 map,一个任务对应一个 map
5.收集 map 的输出,进行分区和排序,这块要注意优化。
6.reduce task 任务启动,并从 map 端拉取数据
7.reduce task 调用自定义的 reduce 函数进行处理
8.调用 outputformat 的 recordwriter 将结果数据输出

並列性決定メカニズムの地図:

データスライスは:入力スライスは、論理的に、ディスク上に格納されている片に切断されておらず、

1.地図段階ジョブ投入クライアントのジョブによって決まる並列度は、スライスの数であります

前記並列処理の分割の例を割り当てられた各スライスmapTask

3.デフォルトでは、タイルのサイズは、ブロックサイズを=

全体的なデータは4スライス、スライスすることによりスライスが、それぞれに別々のファイルを設定して考慮していません

fileInputFormatのスライス工程:

1.程序先找到你数据存储的目录
2.开始遍历处理目录下的每一个文件
3.遍历第一个文件a.txt,
	a.获取文件大小fs.sizeOf(a.txt)
    b.计算切片大小 
    c.开始切, 形成第一个切片,每次切片时,都要片段剩下的部分是否大于块的1.1倍, 不大于1.1倍的就划为一块 
    d.将切片信息写到一个切片规划中 
    e.整个切片过程在getSplit()方法中完成 
    f. InputSplit只记录切片的元数据信息
4.提交切片文件到yarn上, yarn上的appMaster就可以根据切片文件计算开启mapTask个数

MapReduceの最適化:

主要考虑:数据输入,Map阶段, Reduce阶段、IO传输、数据倾斜问题和常用的调优参数 

数据输入: 设置合并小文件/CombineTextInputFormat作为输入, 解决输入端大量小文件场景

map阶段: 减少溢写(spill)次数, 从而减少磁盘IO; 减少合并(Merge次数), 从而缩短MR处理时间; 在map后, 进行combine处理.

reduce阶段: 合理设置map和reduce数. 太少会导致Task等待, 太多会导致map, reduce任务竞争资源, 造成处理超时等错误; 设置map, reduce共存, 使map运行一定程度后, reduce也开始运行; 规避使用reduce, 因为reduce在用于数据集的时候会产生大量网络消耗; 合理设置reduce的buffer

IO传输: 采用数据压缩和序列化二进制文件 比如snappy

数据倾斜: 1.自定义分区2.combine聚合饼精简数据 3.采用mapJoin, 尽量避免reducejoin

worldCountプログラミングケースのMapReduceの:

導入ポンポン依存ファイル:

<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.7.5</version>
        </dependency>

舞台をマップ:

package mapreducedemo;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * @author Jeady
 * @Date 2020/02/07
 */
//自定义Mapper, 继承Mapper
public class WorldCount extends Mapper<LongWritable, Text,Text,LongWritable> {

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

        String[] split = value.toString().split(",");
        for (String s : split) {
            context.write(new Text(s.getBytes()),new LongWritable(1));
        }
    }
}

舞台を減らします:

package mapreducedemo;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * @author Jeady
 * @Date 2020/02/07
 */
//自定义reducer
public class WorldCountReducer extends Reducer<Text, LongWritable,Text,LongWritable> {
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {

        long count = 0;
        for (LongWritable value : values) {
            count += value.get();
        }
        context.write(key,new LongWritable(count));
    }
}

テストの主な方法:

package mapreducedemo;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

/**
 * @author Jeady
 * @Date 2020/02/07
 */
public class WorldMain extends Configured implements Tool {
    @Override
    public int run(String[] args) throws Exception {
        //获取job实例
        Job job = Job.getInstance(super.getConf(), WorldMain.class.getSimpleName());

        //设置输入路径
        job.setInputFormatClass(TextInputFormat.class);
        TextInputFormat.addInputPath(job,new Path("hdfs://node01:8020/worldcount"));

        //设置map类
        job.setMapperClass(WorldCount.class);
        job.setMapOutputKeyClass(LongWritable.class);
        job.setMapOutputValueClass(Text.class);

        //设置reduce类
        job.setReducerClass(WorldCountReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //设置输出路径
        job.setOutputFormatClass(TextOutputFormat.class);
        Path path = new Path("hdfs://node01/world_out");
        TextOutputFormat.setOutputPath(job,path);

        //提交job
        boolean b = job.waitForCompletion(true);
        return b?0:1;
    }

    public static void main(String[] args) throws Exception {
        Configuration configuration = new Configuration();

        WorldMain worldMain = new WorldMain();
        ToolRunner.run(configuration,worldMain,args);
    }
}

三糸スケジューラ:

FIFOスケジューラ(デフォルト):提出のため、順次実行

容量スケジューラスケジューラ容量:各キュー内のFIFO方式に従ってキュースケジューリングの数で構成されるクラスタ、ジョブ

フェアスケジューラ公平スケジューラ:フェアスケジューラがタスクマップに従って最小容量プールをカスタマイズして、スロットの数を減らすために働く、およびサポートプリエンプションに実行中のすべてのジョブ動的なため、システムリソースを調整します

糸スケジューリングプロセス:

1.有YarnClient提交program信息打拼ResourceManager,包括(应用代码和应用需要的一切参数和环境信息)
2.ResourceManager收到请求之后,调用ApplicationMasterManager向NodeManager发送请求,申请一个资源(Container),并且要求Container启动ApplicationMaster.
3.ApplicationMaster启动之后,首先注册自己到ResourceManager,然后为自己的Task申请Container,这个过程是轮训的,循环申请资源,ResourceManager收到请求之后,会要求NodeManager分配资源
4.资源分配完毕之后,Application Master发送请求到NodeManager,启动任务。
5.NodeManager设置Container的运行时环境(jar包,环境变量,任务启动脚本),NodeManager会通过脚本启动任务
6.启动的过程是由NodeManager的ContainerLauncher负责的,ContainerLauncher完成启动任务的工作
7.这一步是在作业执行过程中持续发生的,我用虚线代表,主要包括两类交互,第一,task和Application
Master的交互,task会向AM汇报任务状态和进度信息,比如任务启动,停止,状态更新。ApplicaitonMaster利用这些信息监控task整个执行过程。第二,是NodeManager和ResourceManager的交互,这个过程和任务没有关系,主要是两者之间保持的心跳信息(状态的变化等等)
8.Application Master在检测到作业运行完毕之后,Application Master想Resource Manager
删除自己,并且停止自己执行。

書き込みプロセスをHDFS:

1.客户端向NameNode发出写文件请求。
2.nameNode检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。(注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)
3.client端接收到nameNode的消息, 按128MB的块切分文件。
4.client将NameNode返回的分配的可写的DataNode列表和Data数据一同发送给最近的第一个DataNode节点,此后client端和NameNode分配的多个DataNode构成pipeline管道,client端向输出流对象中写数据。client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。(注:并不是写好一个块或一整个文件后才向后分发)
5.每个DataNode写完一个块后,会返回确认信息。
(注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生)
6.写完数据,关闭输输出流。
7.发送完成信号给NameNode。
(注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)

プロセスを読んでHDFS:

1.client访问NameNode发出查询请求,
2.nameNode查询元数据信息,获得这个文件的数据块位置列表,返回输入流对象。
3.client就近挑选一台datanode服务器,请求建立输入流 。
4.DataNode向输入流中中写数据,以packet为单位来校验。
5.关闭输入流, client接收数据
公開された20元の記事 ウォンの賞賛4 ビュー2721

おすすめ

転載: blog.csdn.net/qq_43149023/article/details/104214879