本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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里的流计算概念,可以说是同一个思想。
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读