Hadoop系列 二

87 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


Hadoop现在已然没落,Spark,Flink也已相当成熟,但是作为老牌分布式计算框架,hadoop有很多值得学习的地方。

这里不是炒冷饭,而是说通过学习一个经典框架,我们可以来看看构建一个nb的框架都具备什么要素。这里主要是从流的角度来看。当然Hadoop个人觉得最经典的东西是在于Mapreduce的思想,分而治之。这个思想可以用数学来证明其计算效率是相当优秀的。

什么是mapreduce

MapReduce 是一种编程范式,可在 Hadoop 集群中的成百上千台服务器上实现大规模可扩展性。作为处理组件,MapReduce 是Apache Hadoop的核心。术语“MapReduce”是指 Hadoop 程序执行的两个独立且不同的任务。第一个是映射作业,它获取一组数据并将其转换为另一组数据,其中单个元素被分解为元组(键/值对)。

reduce 作业将 map 的输出作为输入,并将这些数据元组组合成一组较小的元组。正如 MapReduce 名称的顺序所暗示的那样,reduce 作业总是在 map 作业之后执行。

Mapreduce 输入流

这里直接搬一个官方图来,比较清晰。什么是流?如果你熟悉linux的话,其实管道就是流的一种。或者说,流 其实就是一种思想。任何东西都可以变成了流,然后在不同组建,不同模块之间传递,之后再重新还原成变成流之前的东西。这个思想其实后来衍生出的Spark的RDD,Flink,Storm里的流计算概念,可以说是同一个思想。

image.png

abstract class inputSplit

abstract class InputFormat:

getSplits : split the input files/db/sequecefiles
createRecordReader  : return the RecordReader of one of split of splits

FileInputFormat

TextInputFormat extends FileInputFormat

//计算SplitFile的大小
  protected long computeSplitSize( long blockSize , long minSize,
                                  long maxSize ) {
    return Math.max(minSize , Math.min( maxSize, blockSize));

createRecordReader:

    String delimiter = context.getConfiguration().get(
        "textinputformat.record.delimiter" );
    byte[] recordDelimiterBytes = null ;
    if (null != delimiter)
      recordDelimiterBytes = delimiter.getBytes(Charsets. UTF_8);
    return new LineRecordReader(recordDelimiterBytes );

LineRecordReader:

    // We always read one extra line, which lies outside the upper
    // split limit i.e. (end - 1)
    while (getFilePosition() <= end || in.needAdditionalRecordAfterSplit()) {

LineReader:

  private int bufferSize = DEFAULT_BUFFER_SIZE;
  private InputStream in;
  private byte[] buffer ;
  private int readCustomLine(Text str, int maxLineLength , int maxBytesToConsume)
	//一个一个buffer读