Hadoop中MapReduce整体源码解析

Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster 一、问题描述:Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster 二、解决方法 在Hadoop安装目录下找到mapred-site.xml文件($HADOOP_HOME/etc/hadoop/mapred-site.xml),添加以下配置 <property> <name>yarn.app.mapreduce.am.env</name> 阅读详情

MapReduce整体源码解析:

前言:本文章分析的源码基于Hadoop 3.1.3,主要是针对MR流程过一遍源码,源码的详细解释只涉及一些重要部分,鉴于水平有限,免不了有些说明不够正确,欢迎各位大佬指正。
废话不多说,开搞!

job提交流程:

1. waitForCompletion()提交,进入submit方法,通过connnet方法获取当前job需要执行到本地还是Yarn
//1.waitForCompletion后,进入到job.java中,源码1587行
if (state == JobState.DEFINE) { //判断是否是定义的job
      submit();
    }

//2.进入submit
public void submit()  //源码1560行 
         throws IOException, InterruptedException, ClassNotFoundException {
    ensureState(JobState.DEFINE); //再次确认是否是定义的job
    setUseNewAPI(); //使用新版API
    connect(); 
    //进入connect,步骤:
    //return new Cluster(getConfiguration());
	//初始化操作initialize(jobTrackAddr, conf);  Cluster类中109行
	//根据配置文件的参数信息,通过YarnClientProtocolProvider 获取到  LocalClientProtocolProvider  
	//获取当前job需要执行到本地还是Yarn
	//最终:LocalClientProtocolProvider  ==> LocalJobRunner
    
    final JobSubmitter submitter = 
        getJobSubmitter(cluster.getFileSystem(), cluster.getClient());
    status = ugi.doAs(new PrivilegedExceptionAction<JobStatus>() {
      public JobStatus run() throws IOException, InterruptedException, 
      ClassNotFoundException {
        return submitter.submitJobInternal(Job.this, cluster); //回到job.java,提交job, 1570行
      }
    });
    
2. return submitter.submitJobInternal(Job.this, cluster); 提交job
2.1先通过checkSpecs(job),jobSubmitter中143行; 检查job的输出路径。
// jobSubmitter中268行
private void checkSpecs(Job job) throws ClassNotFoundException, 
      InterruptedException, IOException {
    JobConf jConf = (JobConf)job.getConfiguration();
    // Check the output specification
    if (jConf.getNumReduceTasks() == 0 ? 
        jConf.getUseNewMapper() : jConf.getUseNewReducer()) {
      org.apache.hadoop.mapreduce.OutputFormat<?, ?> output =
        ReflectionUtils.newInstance(job.getOutputFormatClass(),
          job.getConfiguration());
      output.checkOutputSpecs(job); //确认输出路径
    } else {
      jConf.getOutputFormat().checkOutputSpecs(jtFs, jConf);
    }
  }

//进入checkOutputSpecs(job),FileOutputFomat中151行
  public void checkOutputSpecs(JobContext job
                               ) throws FileAlreadyExistsException, IOException{
    // Ensure that the output directory is set and not already there
    Path outDir = getOutputPath(job);
    if (outDir == null) { //假如输出路径没有设置,报错
      throw new InvalidJobConfException("Output directory not set.");
    }

    // get delegation token for outDir's file system
    TokenCache.obtainTokensForNamenodes(job.getCredentials(),
        new Path[] { outDir }, job.getConfiguration());

    if (outDir.getFileSystem(job.getConfiguration()).exists(outDir)) { //路径已存在,报错
      throw new FileAlreadyExistsException("Output directory " + outDir + 
                                           " already exists");
    }
  }
2.2 生成Job提交的临时目录

Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf); //jobSubmitter中148行

file:/tmp/hadoop/mapred/staging/yong1727053970/.staging
2.3为当前Job生成Id
JobID jobId = submitClient.getNewJobID(); //jobSubmitter中157行
2.4确定Job的提交路径
Path submitJobDir = new Path(jobStagingArea, jobId.toString()); //jobSubmitter中159行,尚未创建
2.5创建job的提交路径
copyAndConfigureFiles(job, submitJobDir);//源码第194行
2.6生成切片信息 ,并返回切片的个数(重要,小心!)
int maps = writeSplits(job, submitJobDir); //源码第200行

//具体切片方法在FileInputFomat下的getSplits(), 389行。
public List<InputSplit> getSplits(JobContext job) throws IOException {
    StopWatch sw = new StopWatch().start();
    //getFormatMinSplitSize()返回1,getMinSplitSize(job)默认为0,可以设置参数修改
    long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));//即默认为1
    //默认为Long.MAX_VALUE,很大
    long maxSize = getMaxSplitSize(job);
    
    if (isSplitable(job, path)) { //如果文件是可切分的, 414行
          long blockSize = file.getBlockSize(); //块大小,集群模式下默认128M,本地模式下33554432B(32M)
          long splitSize = computeSplitSize(blockSize, minSize, maxSize); //计算切片大小
    } 
    
    //minsize默认为1,maxsize默认很大,blocksize默认为128M,则此方法默认返回128M
    protected long computeSplitSize(long blockSize, long minSize, long maxSize) {
    	return Math.max(minSize, Math.min(maxSize, blockSize));
  	} //即,如果要增加块大小,可修改配置文件,增大minsize,反之可减小maxsize。
    
    //418行
    long bytesRemaining = length; //文件剩余大小
    	//如果说文件剩余大小 / 切片大小 > SPLIT_SLOP,才继续切块。SPLIT_SLOP为1.1
    	//啥意思呢,就是说如果文件被切了多次,剩余129M,此时块大小是128M的话,那这剩余的文件不会再进行切分,而是被整体当作一个块。这个设定是为了防止数据倾斜。
          while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
            int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
            splits.add(makeSplit(path, length-bytesRemaining, splitSize,
                        blkLocations[blkIndex].getHosts(),
                        blkLocations[blkIndex].getCachedHosts()));
            bytesRemaining -= splitSize;
          }
2.7通过切片的个数设置MapTask的个数
conf.setInt(MRJobConfig.NUM_MAPS, maps); //201行
2.8将当前Job相关的配置信息写到job提交路径下
writeConf(conf, submitJobFile); //245行, 生成job.xml
2.9真正提交Job
status = submitClient.submitJob(
				 jobId, submitJobDir.toString(), job.getCredentials()); //251行

//LocalJobRunner下788行
Job job = new Job(JobID.downgrade(jobid), jobSubmitDir); //构造真正执行的job,之前的job是以用户角度看的
2.10等job执行完成后,删除Job的临时工作目录的内容
jtFs.delete(submitJobDir, true); //262行

MapTask的工作机制

1.接Job提交流程2.9中,转到LocalJobRunnber的内部类Job 的run()方法
//537行,读取job.splitmetainfo
try {
        TaskSplitMetaInfo[] taskSplitMetaInfos = 
          SplitMetaInfoReader.readSplitMetaInfo(jobId, localFs, conf, systemJobDir);
  //获得reduceTask个数 
  int numReduceTasks = job.getNumReduceTasks();
2.根据切片的个数, 创建执行MapTask的 MapTaskRunnable(线程)
//547行
List<RunnableWithThrowable> mapRunnables = getMapTaskRunnables(
            taskSplitMetaInfos, jobId, mapOutputFiles);
3.创建线程池

若是有多个切片,则需要多个maptask,就需要多个线程去执行

ExecutorService mapService = createMapExecutor(); 
4.执行 MapTaskRunnable
runTasks(mapRunnables, mapService, "map");
5.因为Runnable提交给线程池执行,接下来会执行MapTaskRunnable的run方法。

6.执行 LocalJobRunner的内部类Job的内部类MapTaskRunnable 中的run()方法.

//LocalJobRunner中254行
MapTask map = new MapTask(systemJobFile.toString(), mapId, taskId,
            info.getSplitIndex(), 1); //创建MapTask对象

7.执行MapTask中的run方法
//271行
map.run(localConf, Job.this); 

//run方法中执行runNewMapper, 347行
runNewMapper(job, splitMetaInfo, umbilical, reporter); 

//进到runNewMapper
//创建一个context,MapTask中752行
org.apache.hadoop.mapreduce.TaskAttemptContext taskContext =
      new org.apache.hadoop.mapreduce.task.TaskAttemptContextImpl(job, getTaskID(), reporter);

//获取mapper,MapTask中757行
org.apache.hadoop.mapreduce.Mapper<INKEY,INVALUE,OUTKEY,OUTVALUE> mapper =
      (org.apache.hadoop.mapreduce.Mapper<INKEY,INVALUE,OUTKEY,OUTVALUE>)
        ReflectionUtils.newInstance(taskContext.getMapperClass(), job);

//创建inputFormat 761行
org.apache.hadoop.mapreduce.InputFormat<INKEY,INVALUE> inputFormat =
      (org.apache.hadoop.mapreduce.InputFormat<INKEY,INVALUE>)
        ReflectionUtils.newInstance(taskContext.getInputFormatClass(), job);

//重新构建切片对象 765行
org.apache.hadoop.mapreduce.InputSplit split = null;
    split = getSplitDetails(new Path(splitIndex.getSplitLocation()),
        splitIndex.getStartOffset());
    LOG.info("Processing split: " + split);

//获得读取器RecordReader,770行
org.apache.hadoop.mapreduce.RecordReader<INKEY,INVALUE> input =
      new NewTrackingRecordReader<INKEY,INVALUE>
        (split, inputFormat, reporter, taskContext);

//构造缓冲区对象,778行
if (job.getNumReduceTasks() == 0) {
      output =  //如果NumReduceTasks=0,则直接往本地文件写,不走shuffle流程
        new NewDirectOutputCollector(taskContext, job, umbilical, reporter);
    } else {  //不为0,则构建缓冲区
      output = new NewOutputCollector(taskContext, job, umbilical, reporter);
    }
//进入NewOutputCollector  710行
进入collector = createSortingCollector(job, reporter);

collector.init(context);//初始化缓冲区 408行, 进入init方法

final float spillper = //908行
        job.getFloat(JobContext.MAP_SORT_SPILL_PERCENT, (float)0.8); //溢写百分比0.8
final int sortmb = job.getInt(MRJobConfig.IO_SORT_MB,
          MRJobConfig.DEFAULT_IO_SORT_MB); //缓冲区大小100M

sorter = ReflectionUtils.newInstance(job.getClass( //994行
                   MRJobConfig.MAP_SORT_CLASS, QuickSort.class, //获取快速排序对象
                   IndexedSorter.class), job); //不改变元素位置,只根据索引排序

kvbuffer = new byte[maxMemUsage]; //kvbuffer创建 1000行
bufvoid = kvbuffer.length;
kvmeta = ByteBuffer.wrap(kvbuffer).order(ByteOrder.nativeOrder()).asIntBuffer(); //kvmeta

// k/v serialization kv序列化 1017行
// output counters 计数器 1027行
// compression 压缩 1034行
// combiner 1043行

------缓冲区构建完成--------
    
//缓冲区构建完成后,根据NumReduceTasks获得分区器
    partitions = jobContext.getNumReduceTasks(); //711行
      if (partitions > 1) {
        partitioner = (org.apache.hadoop.mapreduce.Partitioner<K,V>)
          ReflectionUtils.newInstance(jobContext.getPartitionerClass(), job);
      } else {
        partitioner = new org.apache.hadoop.mapreduce.Partitioner<K,V>() {
          @Override
          public int getPartition(K key, V value, int numPartitions) {
            return partitions - 1;
          }
        };

// 执行WordCountMapper中的run方法。 实际执行的是WordCountMapper继承的Mapper中的run方法。  799行
mapper.run(mapperContext); 


//进入在Mapper中的run方法中 
public void run(Context context) throws IOException, InterruptedException {
    setup(context);
    try {
      while (context.nextKeyValue()) {
        map(context.getCurrentKey(), context.getCurrentValue(), context); //执行用户的map方法
      }
//不断执行context.write(outK,outV),每次写出一对KV都会被缓冲区收集 
 

Shuffle流程

1.进入context.write(outK,outV)
//WrapperMapper类下,是Mapper的包装类
mapContext.write(key, value); //112行

//再进入
output.write(key, value); //89行

//再进人  MapTask下,将map写出的kv 计算好分区后,收集到缓冲区中。
collector.collect(key, value, partitioner.getPartition(key, value, partitions)); //727行

//进入collect方法,若满足溢写条件,开始发生溢写
startSpill(); //Maptask下1126行

spillReady.signal(); //线程间的通信,通知溢写线程开始溢写 1602行 

//溢写线程调用 sortAndSpill() 方法发生溢写操作
private void sortAndSpill() throws IOException, ClassNotFoundException, InterruptedException{//1609
      //approximate the length of the output file to be the length of the
      //buffer + header lengths for the partitions
      final long size = distanceTo(bufstart, bufend, bufvoid) +
                  partitions * APPROX_HEADER_LENGTH;
      FSDataOutputStream out = null;
      FSDataOutputStream partitionOut = null;
      try {
        // create spill file
        final SpillRecord spillRec = new SpillRecord(partitions); //根据分区创建溢写文件
        final Path filename =
            mapOutputFile.getSpillFileForWrite(numSpills, size);
        out = rfs.create(filename);
      }
}
 
//溢写前先进行排序 1625行
sorter.sort(MapOutputBuffer.this, mstart, mend, reporter);

// 进行溢写操作,1629行
for (int i = 0; i < partitions; ++i) { //根据分区溢写
          IFile.Writer<K, V> writer = null;
          try {
            long segmentStart = out.getPos();
            partitionOut = CryptoUtils.wrapIfNecessary(job, out, false);
            writer = new Writer<K, V>(job, partitionOut, keyClass, valClass, codec,
                                      spilledRecordsCounter);
            if (combinerRunner == null) { //如果没有设置combiner,则直接溢写
              // spill directly
              DataInputBuffer key = new DataInputBuffer();
              while (spindex < mend &&
                  kvmeta.get(offsetFor(spindex % maxRec) + PARTITION) == i) {
                final int kvoff = offsetFor(spindex % maxRec);
                int keystart = kvmeta.get(kvoff + KEYSTART);
                int valstart = kvmeta.get(kvoff + VALSTART);
                key.reset(kvbuffer, keystart, valstart - keystart);
                getVBytesForOffset(kvoff, value);
                writer.append(key, value);
                ++spindex;
              }
            } else {
              int spstart = spindex;
              while (spindex < mend &&
                  kvmeta.get(offsetFor(spindex % maxRec)
                            + PARTITION) == i) {
                ++spindex;
              } 
            }
          }
}

//溢写完成,关闭
writer.close(); //1667行

//map持续往缓冲区写,达到溢写条件,就继续溢写 ........ 可能整个过程中发生N次溢写。

//假如上一次溢写完后,剩余进入的到缓冲区的数据没有达到溢写条件,那么当map中的所有的数据都已经处理完后,在关闭output时,会把缓冲区中的数据刷到磁盘中(其实就是没有达到溢写条件的数据也要写到磁盘)
output.close(mapperContext); //805行

//进入close,数据刷写,735行
collector.flush();

//进入flush,通过溢写的方法进行剩余数据的刷写 1505行
sortAndSpill();

//溢写完成后,进行归并 1527行
mergeParts();

for(int i = 0; i < numSpills; i++) {
        filename[i] = mapOutputFile.getSpillFile(i);
        finalOutFileSize += rfs.getFileStatus(filename[i]).getLen();
      } //根据溢写的次数,得到要归并多少个溢写文件 //1852行

//生成最终存储数据的两个的文件(目前是空的)
Path finalOutputFile =
          mapOutputFile.getOutputFileForWrite(finalOutFileSize); //内容
Path finalIndexFile =
          mapOutputFile.getOutputIndexFileForWrite(finalIndexFileSize); //索引


//按照分区进行归并 1925行
for (int parts = 0; parts < partitions; parts++) {
          //create the segments to be merged
          List<Segment<K,V>> segmentList =
            new ArrayList<Segment<K, V>>(numSpills);
}
//归并
RawKeyValueIterator kvIter = Merger.merge(job, rfs, //1950行
                         keyClass, valClass, codec,
                         segmentList, mergeFactor,
                         new Path(mapId.toString()),
                         job.getOutputKeyComparator(), reporter, sortSegments,
                         null, spilledRecordsCounter, sortPhase.phase(),
                         TaskType.MAP);
//将归并的文件写入磁盘 1959行
long segmentStart = finalOut.getPos();
finalPartitionOut = CryptoUtils.wrapIfNecessary(job, finalOut, false);
Writer<K, V> writer = //创建输出流
    new Writer<K, V>(job, finalPartitionOut, keyClass, valClass, codec, spilledRecordsCounter);
if (combinerRunner == null || numSpills < minSpillsForCombine) { //如果combiner为空或者溢写次数少于
    Merger.writeFile(kvIter, writer, reporter, job);  //minSpillsForCombine(默认为3),则不走combine
} else {
    combineCollector.setWriter(writer);
    combinerRunner.combine(kvIter, combineCollector);
}
//归并完成,关流 1972
writer.close();

//删除溢写文件 1991
for(int i = 0; i < numSpills; i++) {
    rfs.delete(filename[i],true);
}

//剩余file.out  file.out.index,等待reduce的拷贝

ReduceTask机制

1.在LocalJobRunner的内部类Job中的run()方法中

try {
   if (numReduceTasks > 0) {//根据设置的reduceTask的个数,创建对应个数				  			  								LocalJobRunner$Job$ReduceTaskRunnable
         List<RunnableWithThrowable> reduceRunnables = getReduceTaskRunnables(
                jobId, mapOutputFiles);
         ExecutorService reduceService = createReduceExecutor();
         unTasks(reduceRunnables, reduceService, "reduce");
          }
}   
//执行LocalJobRunner$Job$ReduceTaskRunnable 中的run方法
//创建ReduceTask对象 334行
ReduceTask reduce = new ReduceTask(systemJobFile.toString(),reduceId, taskId, mapIds.size(), 1);

// 执行ReduceTask的run方法 347行
reduce.run(localConf, Job.this);

//进入ReduceTask类
//run方法中,先设置步骤 324行
if (isMapOrReduce()) {
      copyPhase = getProgress().addPhase("copy");
      sortPhase  = getProgress().addPhase("sort");
      reducePhase = getProgress().addPhase("reduce");
    }
//copy,sort过程省略吧,好累了

// 然后runNewReducer //390行
if (useNewApi) {
      runNewReducer(job, umbilical, reporter, rIter, comparator, keyClass, valueClass);
    }

//执行WordCountReducer的run方法 ,实际执行的是WordCountReducer继承的Reducer类中的run方法. 628行
reducer.run(reducerContext); 

//进入run方法 171行
reduce(context.getCurrentKey(), context.getValues(), context); //终于执行到用户WordCountReducer中的 reduce方法.

context.write(k,v) //用户的reduce中将处理完的kv写出.
    
reduceContext.write(key, value); //105行
output.write(key, value); //89行
real.write(key,value);  // 通过RecordWriter将kv写出 559行
out.write(NEWLINE);  //通过输出流将数据写到结果文件中 101行

//终于结束了,写这些框架的人都是怎么样的天才!

尚硅谷大数据技术Hadoop教程-笔记07【Hadoop-源码解析】 阅读详情

相关推荐

南京邮电大学《数学实验》模块二(函数的迭代)参考答案

【代码】南京邮电大学《数学实验》模块二(函数的迭代)参考答案。

qq_1293730064的博客 3万+

错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster

执行hive出现错误,在resourcemanage上找到错误: 今天在安装完 hadoop 3.2.1 版本后,执行 MapReduce 操作时,出现错误, 提示找不到主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster 。 在网上搜索找到解决方法,记录如下: 在命令行下输入如下命令,并将返回的内容复制。 # hadoop classpath 编辑 yarn-site.xml # vim yarn-site.xml ...

sjunothing的博客 9277

KEPServerEX与三菱iQ-R系列PLC通讯

KEPServerEX与三菱iQ-R系列PLC通讯Mitsubishi Ethernet北京东方鼎晨科技有限公司目 录1. 前言2. 三菱PLC端相关设置3. Kepware端相关设置KEPServerEX是美国PTC Kepware公司生产的具有行业性的连接平台,KEPServerEX支持150多种通讯协议,用于向您的所有应用程序提供单一来源的工业自动化数据。该平台的设计使用户能够通过一个直观的用户界面来连接、管理、监视和控制不同的自动化设备和软件应用程序。KEPServerEX利用OPC(自动化产业的互

qq_28768521的博客 8096

解决:Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster

错误:Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster 问题描述: 无法找到或加载主类 解决: 停止hadoop的运行。 stop-all.sh 编辑mapred-site.xml vi mapred-site.xml 加入以下内容 #/training/hadoop-3.1.3是我的Hadoop的安装目录,改成你的 <property> <n..

qq_55906442的博客 5287

STM32F4系列HAL库配置定时器实验——输入捕获

STM32F4系列HAL库配置定时器实验——输入捕获 输入捕获简单讲解 输入捕获模式可以用来测量脉冲宽度或者测量频率。我们以测量周期和频率为例,用一个简图来说明输入捕获的原理 假定定时器工作在向上计数模式, 图中 t1~t2 时间,就是我们需要测量的高电平时间。测量方法如下:首先设置定时器通道 x 为 上升沿捕获,这样,t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。这样,根据定时器

azs0504的博客 9286

带挂牵引车倒车运动模型推导及仿真实现

半挂牵引车在倒车时,由于鞍座主销的连接限制,其运动方式与乘用车有显著差异。例如,乘用车在右侧倒车入库时,只需确定泊车起点并将方向盘向右打死。相反,牵引车在倒车时需要先向左转方向盘,当铰接角达到防折叠的临界值时,再将方向盘向右转回,以调整牵引车与挂车至直线状态,完成泊车入库。本研究旨在建立一个基于牵引车带挂车倒车运动学模型,该模型基于以下假设: 道路在车辆行驶过程中保持平坦,无凹凸不平; 车辆以低速行驶,且在运行过程中车身不发生侧倾或俯仰; 行驶过程中,轮胎无变形,无侧向滑动,且不产

jianmo的博客 2697

初学Hadoop之图解MapReduce与WordCount示例分析

阅读目录 1、MapReduce整体流程2、WordCount源码3、WordCount逐行解析   Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。   HDFS是Google File System(GFS)的开源实现,MapReduce是Google MapReduce的开源实

易水寒 1770

C#单例模式在工控上位机的实战应用:一台设备只连一次,稳定运行7×24小时

在工控行业,稳定性比功能更重要。一台上位机需要7×24小时运行,任何一次因资源冲突导致的停机,都可能给工厂带来巨大损失。单例模式的核心价值,就是通过保证资源唯一性,避免PLC连接冲突、串口占用、日志写入错乱等问题,为工控上位机的稳定运行保驾护航。按需使用:不是所有类都要单例,只有资源唯一性的类才用;线程安全:多线程场景下,必须用双重检查锁定或静态内部类写法;手动释放:单例类中的硬件资源(PLC、串口),程序退出时必须手动释放,避免资源泄漏。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 549

【Big Data - Hadoop - MapReduce】初学Hadoop之图解MapReduce与WordCount示例分析

Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。 HDFS是Google File System(GFS)的开源实现。 MapReduce是Google MapReduce的开源实现。 HDFS和MapReduce实现是完全分离的,并不是没有HDFS就不能MapReduce运算。 本文主要参考了以...

weixin_34409822的博客 287

AFL源码分析之afl-as.c详细注释

前言 afl-as注释好了,明白了是如何进行插桩的,以及插在哪里 本文主要参考Sakura大佬文章:https://eternalsakura13.com/2020/08/23/afl/ 编写不易,如果能够帮助到你,希望能够点赞收藏加关注哦Thanks♪(・ω・)ノ /* Copyright 2013 Google LLC All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); y

hollk’s blog 2172

智能车图像处理22-进阶篇14--小s的判断

这篇文章中主要讲述智能车图像处理中 : 小s的判断方法。

taiyuezyh的博客 2566

hadoop 的helloword 的wordcount程序

http://www.tuicool.com/articles/v6VNza Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。 HDFS是Google File System(GFS)的开源实现。 MapReduce是Google MapReduce的开源实现。 HDFS和Ma

滴水可以穿石 百炼才能成钢,谋全局而通一域 致广大而尽精微 447

【STM32项目】基于Stm32c8t6-镭射激光打印机的设计(完整工程资料源码)

随着打印技术的快速发展,镭射打印技术也开始得到越来越广泛的应用。这种技术可以被用于在木材、塑料、皮革、织物等各种材料上进行图形打印,并且通常比传统机器更快、更准确和更灵活。

嵌入式技术开发 7198

MapReduce框架原理 InputFormat数据输入

一、MapReduce整体架构 二、切片与MapTask并行度决定机制 1)问题引出 MapTask的并行度决定Map阶段的任务处理并发度,进而影响到整个Job的处理速度。 思考:1G的数据,启动8个MapTask,可以提高集群的并发处理能力。那么1K的数据,也启动8个MapTask,会提高集群性能吗?MapTask并行任务是否越多越好呢?哪些因素影响了MapTask并行度? 2)MapTask并行度决定机制 数据块:Block是HDFS物理上把数据分成一块一块。数据块是HDFS存储数据单位。 数据切

mengxianglong123的博客 192

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

wordcount示例分析

Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。   HDFS是Google File System(GFS)的开源实现,MapReduce是Google MapReduce的开源实现。   HDFS和MapReduce实现是完全分离的,并不是没有HDFS就不能MapReduce运算。 本文主要参考了以下...

Accepted ALL lve 726

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

MapReduce框架源码解析

MapReduce框架源码解析

Deegue 2万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Hadoop之图解MapReduce与WordCount示例分析

Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。   HDFS是Google File System(GFS)的开源实现,MapReduce是Google MapReduce的开源实现。   HDFS和MapReduce实现是完全分离的,并不是没有HDFS就不能MapReduce运算。 本文主要参考

大数据指北 1万+

Hadoop YARN MapReduce 作业全生命周期深度解析

分层解耦:YARN将资源调度与应用管理分离,MapReduce自身又将作业、任务、数据、状态分层,便于弹性扩展和容错。数据本地性优先:调度优先考虑数据本地,减少跨节点IO。异步批量处理:资源申请与任务调度均采用异步批量,提升吞吐。参数动态调优:生产环境需结合数据量、资源动态调整参数,批量作业可自动化调优。监控与追踪闭环:利用YARN Web UI、JobHistoryServer、AM/Task日志构建全链路监控。分阶段图文梳理源码、参数、案例总结设计思想与方法论结合生产问题分析与调优实践。

IT技术学习与工作笔记分享 1055

mapreduce实现wordcount 详细解析

总括 Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。 HDFS是Google File System(GFS)的开源实现,MapReduce是Google MapReduce的开源实现。 HDFS和MapReduce实现是完全分离的,并不是没有HDFS就不能MapReduce运算。 1、MapReduce整体流程 最简单的MapReduce应用程序至少包含 3 个部分:一个 Map 函数、一个 Reduce 函数

qq_38924865的博客 6047

Hadoop源码分析(1)————MapReduce之整体流程分析

欢迎来到何大鹰的Hadoop理解内容由于Hadoop已经火了有一段时间啦~,所以编译hadoop和部署hadoop的内容在这里我就不多讲了,编译hadoop大家可以看看这篇博客https://blog.csdn.net/cruise_h/article/details/18709969 至于部署hadoop大家完全可以按照官网上的文档慢慢配置,还可以练习一下英文阅读能力。 运行和编译hadoop

qq_33771258的博客 441

基于Hadoop MapReduce的空气质量数据分析系统:从架构到源码深度解析

本文介绍了一个基于Hadoop MapReduce的空气质量大数据分析系统。系统采用前后端分离架构,包含MapReduce数据处理、Spring Boot后端和Vue.js前端三大模块,实现了15项核心空气质量指标分析。文章详细解析了系统架构设计、技术选型(Hadoop 3.3.1、Spring Boot 2.7.18、Vue 3.4.21等)以及核心源码实现,重点展示了MapReduce驱动程序配置、Combiner优化技术、Mapper数据清洗和异常处理等关键技术细节。该系统能够高效处理海量空气质量数据

2301_79641396的博客 767
上一篇: Airbnb(爱彼迎)产品分析报告
下一篇: Hive中 Order by,Sort by, Distribute by, Cluster by详解
dab-hand
博客等级 码龄7年 10粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值