Hadoop中HDFS、MapReduce的运行原理

HDFS的运行过程

概念:
namenode:负责记录 数据块 的分布情况– 数据元数据信息
datanode:负责实际存储 数据块
block:是Hadoop最小存储数据单位 默认 128M
secondarynamenode: 辅助namenode完成fsimage管理或者优化

当用户将文件上传到HDFS中时,首先会将文件信息放入namenode进行处理,hadoop的储存文件以块为单位,会把每个文件会按照块来进行拆分,每个块的大小为128M(也正是因此hadoop不适合用来储存小文件,因为每个小文件都会独占一个block),所存储的信息内容包括每个块所对应的源文件内容,分储存至哪个DataNode,以及有几个副本(信息被称为fsimage)。同时被拆分的文件块会随机存入数个DataNode中,实现数据的存储

Namenode在第一次启动时会将fsimage镜像文件加载到内存(在此期间会进入安全模式:对外读写都是不可用的)。文件变动时直接对内存进行修改,并将修改信息存入edits日志。Edit记录了对内存的修改。Secondaryamenode会定时的从namenode中下载editsfsimage,时,namenode中会产生一个新的edits_progress,存储修改信息。Secondnamenode中会对下载得到的数据并对其进行合并,得到了一个新的fsimage。之后fsimage将上传至namenode中形成fsimage_chkfsimage_ckeedits_progress组合成为最新的数据文件。

HadoopMapReduce运行原理

MapTask阶段

①进入环状缓冲区

Inputsplit经过切片计算阶段处理后(检查目录是否为空–>上传jar包–>计算切片将切片信息写入Hdfs)进入buffer in memory(默认每一个MapTask都有一个100M的环状缓冲区,用于储存Map输出的key-value。每个缓冲区都有一个缓冲阀值0.8,MapTask会有一个SpillThread的线程,负责监控缓冲区的变化,一旦达到缓冲区80%的占用,该线程将这80%的内容flush到磁盘,这个过程称为溢写。每一次溢写都会产生一个溢写文件SpillFile进入本地磁盘)
溢写:缓冲区–>分区–>排序–>flushe磁盘–>形成溢写文件

②分区

每一个溢写文件都会根据设定的代码进行分区,默认分区依据是对key进行hash计算,取膜并根据结果进行分区。源码如下:
可以通过自己写类继承Patitoner(class

//设置分区
job.setPartitionerClass(CutomPartitioner.class);
job.setNumReduceTasks(3);//part-r-00000

//自定义分区依据
public class CutomPartitioner extends Partitioner<Text, IntWritable> {
    @Override
    public int getPartition(Text key, IntWritable value, int numPartitions) {
        // TODO Auto-generated method stub
        return 3;
    }
}
③排序

局部有序(先分区 再排序)

排序规则
依据Writable类实现WritableComparable 中的compareTo实现,代码如下:

public int compareTo(CityWritable o) {
    // TODO Auto-generated method stub
    System.out.println("=======compareTo=======");
    if(this.year.compareTo(o.getYear())!=0){
        return this.year.compareTo(o.getYear());
    }else if(this.tempreture.compareTo(o.getTempreture())!=0){
        return this.tempreture.compareTo(o.getTempreture());
    }else{
        return this.cityName.compareTo(o.getCityName());    
    }
    return 0;
}

自己写一个Comparator继承WritableComparator并覆盖里面的compareTo方法
(注意要写构造方法)通过设置外部比较器应用对应排序类

//设置外部比较器
job.setSortComparatorClass(YearComparator.class);
public class YearComparator extends WritableComparator {
    public YearComparator(){
        super(CityWritable.class,true);
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        // TODO Auto-generated method stub
        CityWritable c1=(CityWritable) a;
        CityWritable c2=(CityWritable) b;
        System.out.println("=======compare=======");
        if(c1.getTempreture().compareTo(c2.getTempreture())!=0){
            return c1.getTempreture().compareTo(c2.getTempreture());
        }else if(c1.getYear().compareTo(c2.getYear())!=0){
            return c1.getYear().compareTo(c2.getYear());
        }else{
            return c1.getCityName().compareTo(c2.getCityName());    
        }   
    }
}

全局有序(分区有序即可)

//设置分区
job.setPartitionerClass(YearPartitioner.class);

public class YearPartitioner extends Partitioner<CityWritable, NullWritable> {
    @Override
    public int getPartition(CityWritable key, NullWritable value,
            int numPartitions) {
        // TODO Auto-generated method stub
        return key.getYear().get()%numPartitions;
    }
}

辅助排序SecondarySort(在reduce端排序)分组

//设置分组依据
job.setGroupingComparatorClass(YearGroupComparator.class);

public class YearGroupComparator extends WritableComparator {
    public YearGroupComparator(){
        super(CityWritable.class,true);
    }
    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        // TODO Auto-generated method stub
        CityWritable c1=(CityWritable) a;
        CityWritable c2=(CityWritable) b;
        return c1.getYear().compareTo(c2.getYear());
    }   
}
④combiner

Combinner:使Map端输出结果更加紧凑.使部分数据在Map端提前执行Reduce的逻辑.设置Combinner必须要求Map端的输出吻合Reducer端输出.
优点:减少key的排序(Map端/Shuflle阶段 key数量) / 减少Shuffle的数据量 节省网络带宽
运行时机:产生溢写/溢写文件合并

设置combiner方法

job.setCombinerClass(WordReducer.class);
⑤压缩
//设置输出结果压缩
TextOutputFormat.setCompressOutput(job, true);
TextOutputFormat.setOutputCompressorClass(job, GzipCodec.class);

//开启Map压缩 减少shuffle过程的网络带宽占用(只能在真实环境测试)
conf.setBoolean("mapreduce.map.output.compress", true);
conf.setClass("mapreduce.map.output.compress.codec",
GzipCodec.class, CompressionCodec.class);

Shuffle阶段

下载分区(fetch)
数据合并
数据排序

reduce阶段整合

整合运算


思考:Mapreduce到底是什么 ?

谁决定了Mapreduce计算的数据?
InputForamt
谁决定了Mapreduce输出?
OutputFormat
MapReduce和HDFS关系是什么?
MapReduce是一个并行计算框架,仅仅是利用了HDFS集群中Datanode机器CPU和内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值