MapReduce编程

Hadoop的MapReduce计算框架

概述

  • MapReduce计算框架是一种计算框架,用于计算处理大规模的数据集,他将数据分成小块,然后在集群中的多个节点上并行处理这些块
  • MapReduce框架是由两个组件组成:Map和Reduce
    • Map任务将输入数据分解成键值对,然后将这些键值对传递给Reduce任务进行处理
    • Reduce任务将相同的所有值组合在一起,并将它们转换为输出键值对
  • 这种分布式计算框架可以在大规模数据集上高效地运行,因为它可以利用集群中的多个节点并行处理数据。

MapReduce是一种分布式计算模型,用于处理大规模数据集。它将数据分成多个小块,然后在多个计算节点上并行处理这些小块。MapReduce的工作原理如下:

  • Map阶段:将输入数据分成多个小块,然后在多个计算节点上并行处理这些小块。每个计算节点都会执行Map函数,将输入数据转换成键值对。

  • Shuffle阶段:将Map函数的输出结果按照键进行分组,然后将同一组的键值对发送到同一个Reduce节点上。

  • Reduce阶段:将同一组的键值对发送到同一个Reduce节点上,然后在该节点上执行Reduce函数,将同一组的键值对合并成一个结果。

  • 输出结果:将所有Reduce节点的输出结果合并成一个最终结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AuLTOMwz-1686616882602)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230525094357692.png)]

特点

  • 可扩展性
    • MapReduce框架可以在大规模数据集上高效地运行,因为它可以利用集群中的多个节点并行处理数据。
  • 容错性
    • MapReduce框架具有容错机制,可以处理节点和数据丢失等问题
  • 简单性
    • MapReduce框架的编程模型相对简单,可以轻松地编写Map和Reduce任务
  • 适用性
    • MapReduce框架适用于各种类型地数据处理任务,包含文本处理,图像处理,机器学习等。

优缺点

优点:

  • 可以处理大规模的数据集,具有良好的可扩展的容错性,
  • 可以在分布式的环境下运行,可以利用集群中的多台计算机进行计算,提高计算效率
  • 可以通过MapReduce编程模型进行编程,简化了分布式计算的开发难度
  • 可以与HDFS文件系统和YARN资源管理系统配合使用,构建完整的分布式计算平台

缺点:

  • MapReduce编程模型对于一些复杂的计算任务来说,可能不太适合
  • MapReduce编程模型需要将计算任务分成Map阶段和Reduce阶段,可能会导致计算效率的降低
  • MapReduce编程模型需要将数据写入磁盘,可能会导致I/O开销较大

进程

MapReduce进程包括两个主要的进程:JobTracker进程和TaskTracker进程,

  • JobTracker进程负责接收客户端提交的MapReduce任务,并将任务分配给TaskTracker进程执行;
  • TaskTracker进程负责执行MapReduce任务,并将执行结果返回给JobTracker进程。
  • JobTracker进程和TaskTracker进程都运行在Hadoop集群中的计算节点上,它们之间通过心跳机制进行通信,以保证任务的正确执行。

JobTracker进程:

  • JobTracker进程是MapReduce进程中的主进程,负责接收客户端提交的MapReduce任务,并将任务分配给TaskTracker进程执行。
  • JobTracker进程运行在Hadoop集群中的一台计算节点上,它通过心跳机制与TaskTracker进程进行通信,以监控任务的执行情况。
  • JobTracker进程还负责维护任务的元数据信息,包括任务的状态、进度、日志等。

TaskTracker进程

  • TaskTracker进程是MapReduce进程中的工作进程,负责执行MapReduce任务,并将执行结果返回给JobTracker进程。
  • TaskTracker进程运行在Hadoop集群中的计算节点上,它通过心跳机制与JobTracker进程进行通信,以接收任务的分配和监控任务的执行情况。
  • TaskTracker进程还负责维护任务的本地数据,包括输入数据、输出数据、中间结果等。

常见的配置

  1. 输入格式:MapReduce框架支持多种输入格式,包括文本、序列化、Hadoop Archives等。可以根据数据类型选择合适的输入格式。
  2. 输出格式:MapReduce框架支持多种输出格式,包括文本、序列化、Hadoop Archives等。可以根据需要选择合适的输出格式。
  3. Map任务数:MapReduce框架默认将输入数据分成64MB的块,并为每个块分配一个Map任务。可以根据数据大小和集群规模调整Map任务数。
  4. Reduce任务数:Reduce任务数的数量通常与集群中的节点数相同。可以根据集群规模和数据大小调整Reduce任务数。
  5. Combiner函数:Combiner函数是一种在Map任务输出之前对Map任务输出进行合并的函数。可以使用Combiner函数来减少Map任务输出的数据量,从而提高MapReduce框架的效率。
  6. Partitioner函数:Partitioner函数是一种将Map任务输出分配到Reduce任务的函数。可以根据键的哈希值将Map任务输出分配到不同的Reduce任务中。
  7. 缓存文件:MapReduce框架支持将文件缓存在内存中,以便在Map和Reduce任务中使用。可以使用DistributedCache类将文件缓存到集群中的节点上。
  8. 压缩:MapReduce框架支持对输入和输出数据进行压缩,以减少数据传输的大小。可以使用Gzip、Bzip2等压缩算法对数据进行压缩。
  9. 计数器:MapReduce框架支持计数器,用于记录任务的进度和状态。可以使用计数器来监视任务的执行情况。

WordCount编程

本地测试

需求:在给定的文件中统计输出的每个单词出现的总次数

package com.sin.mapRedice;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/**
 * @CreateName SIN
 * @CreateDate 2023/05/26 11:33
 * @description
 */
public class WordCount {

    /**
     * Mapper:将输入键/值映射到一组中间键/值对中
     */
    public static class TokenizerMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
        //创建IntWritable对象
        private final static IntWritable one = new IntWritable(1);
        //创建Text对象
        private Text word = new Text();

        /**
         * 对输入分割中的每一个键/值调用一次
         * @param key 键
         * @param value 值
         * @param context 上下文
         * @throws IOException
         * @throws InterruptedException
         */
        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            //将输入的文本数据转换为StringToKenizer对象
            StringTokenizer itr = new StringTokenizer(value.toString());
            //遍历StringTokenizer对象中的每一个单词
            while (itr.hasMoreTokens()) {
                //将当前单词设置为Text类型的值
                word.set(itr.nextToken());
                //将当前单词和IntWritable对象写入上下文中
                context.write(word, one);
            }
        }
    }

    public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

        private IntWritable result = new IntWritable();

        /**
         * 接收键值对列表,将相同键的值相加并输出
         * @param key 键
         * @param values 值的迭代器
         * @param context 上下文
         * @throws IOException
         * @throws InterruptedException
         */
        public void reduce(Text key, Iterable<IntWritable> values, Context context)
                throws IOException, InterruptedException {
            //定义一个变量sum,用来存储values中的所有元素的和
            int sum = 0;
            //遍历values中的所有元素
            for (IntWritable val : values) {
                //将元素的值添加到sum中
                sum += val.get();
            }
            //将相加后的结果设置为IntWritable对象的值
            result.set(sum);
            // 将 key 和 sum 作为输出写入 context
            context.write(key, result);
        }
    }

    public static void main(String[] args) throws Exception {
        // 创建Configuration对象
        // 配置由资源指定,资源包含一组名称/值对作为xml数据,
        // 每个资源都是由字符串或者路径命名
        // 如果使用String命名,则检查类路径以查找具有改名称的文件
        // 如果以Path命名,则直接检查本地文件系统,而不引用类路径
        Configuration conf = new Configuration();
        /**
         * 创建job对象
         *    任务提交者对任务的视图
         *    它允许用户配置任务,提交任务,控制其执行和查询状态,
         */
        //获取实例
        Job job = Job.getInstance(conf, "word count");
        //设置jar包
        job.setJarByClass(WordCount.class);

        //关联mapper和reducer
        job.setMapperClass(TokenizerMapper.class);
        job.setCombinerClass(IntSumReducer.class);
        job.setReducerClass(IntSumReducer.class);

        //设置最终输出的kv类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        //设置输入路径
        FileInputFormat.addInputPath(job, new Path("F:\\input"));
        //设置输出路径
        FileOutputFormat.setOutputPath(job, new Path("F:\\output\\outputword"));

        //提交任务并等待完成
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

测试异常

解决java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WShxd3gf-1686616882603)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526154946261.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmkOSU0z-1686616882603)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526154959408.png)]

解决Exception in thread “main” java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z

return后面删了。然后改为true,但是这里是只读文件不能修改,所以创建一个类就行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aZtujHwZ-1686616882604)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155219123.png)]

复制包路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-76NaZBzW-1686616882604)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155248825.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-alEPMyd8-1686616882604)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155316654.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePAZuIiz-1686616882605)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155330903.png)]

创建NativeIO类并修改access方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3qgdSZJ-1686616882605)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155421525.png)]

输出结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xjCe8MNS-1686616882606)(E:\Java笔记\大数据\Hadoop\Hadoop的MapReduce计算框架\Hadoop的MapReduce计算框架.assets\image-20230526155510311.png)]

集群测试

package com.sin.demo;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.mapreduce.Counter;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;

public class WordCount {

    /**
     * 使用静态内部类来编写map部分
     * 继承MapReduceBase类:提供了Mapper和Reducer类的基本实现
     * 实现Mapper接口:
     * LongWritable:输入数据的键的类型,通常用于表示行的偏移量或其他唯一标识符。在大多数情况下,它表示文本文件中每行的偏移量。
     * Text:        输入数据的值的类型,通常用于表示文本数据。在大多数情况下,它表示文本文件中的一行或一段文本。
     * Text:        输出键的类型,通常用于表示单词或某种标识符。
     * IntWritable:输出值的类型,通常用于表示某个计数或数量。
     */
    public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
        private final static IntWritable one = new IntWritable(1); // 一个单词的出现次数
        private Text word = new Text(); // 单词

        /**
         * map 方法用于将输入的文本分割成字符串并输出 <字符串, 1> 键值对
         * @param key 健
         * @param value 值
         * @param output 收集 Mapper 输出的键值对并将其传递给 Reducer 的接口。收集 Text 类型键和 IntWritable 类型值的输出收集器
         * @param reporter 报告任务的进度和状态。允许Mapper和Reducer向作业跟踪器(JobTracker)发送关于它们的进度和状态的信息
         * @throws IOException
         */
        public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
            // 将输入数据转换为字符串
            String line = value.toString();
            // 将每一个字符串之间添加空格
            StringTokenizer tokenizer = new StringTokenizer(line);
            // 遍历数据
            while (tokenizer.hasMoreTokens()) {
                // 将字符串存储到Text文本类型中
                word.set(tokenizer.nextToken());
                // 输出单词及其出现次数 (word作为健,one作为值)
                output.collect(word, one);
            }
        }
    }

    /**
     *使用静态内部类来编写Reducer部分
     *继承了MapReducedBase类:Mapper和Reducer类的基本实现
     * 实现了Reduce接口:
     * Text:        输入键的类型,通常是Mapper输出键的类型。表示的是字符串。
     * IntWritable: 输入值的类型,通常是Mapper输出值的类型。表示的是字符串出现的次数。
     * Text:        输出键的类型,通常是最终结果的键的类型。表示的仍然是字符串。
     * IntWritable:输出值的类型,通常是最终结果的值的类型。表示的是字符串出现的总次数。
     */
    public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {

        /**
         *
         * @param key 文本类型的健
         * @param values 迭代器,Reducer的输入是一组键值对,其中键是某个特定的字符串,而值则是该字符串在不同位置出现的次数集合
         * @param output 收集Reducer输出的类
         * @param reporter 报告任务的进度和状态。允许Mapper和Reducer向作业跟踪器(JobTracker)发送关于它们的进度和状态的信息
         * @throws IOException
         */
        // reduce 方法将相同的单词键合并,并将它们的值相加
        public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
            // 记录字符串出现的次数
            int sum = 0;
            // 遍历字符串
            while (values.hasNext()) {
                sum += values.next().get(); // 累加相同单词的出现次数
            }
            // 输出字符串及其总次数
            output.collect(key, new IntWritable(sum));
        }
    }

    // 主函数
    public static void main(String[] args) throws Exception {
        /**
         * 创建一个 JobConf 对象来配置作业
         * JobConf是Hadoop MapReduce中的一个类,用于配置MapReduce作业的各种参数和属性
         * 如输入路径、输出路径、Mapper类、Reducer类等
         */
        JobConf conf = new JobConf(WordCount.class);
        // // 设置作业名称
        conf.setJobName("wordcount");

        // 设置输出键和值的类型
        conf.setOutputKeyClass(Text.class);
        conf.setOutputValueClass(IntWritable.class);

        // 设置 Mapper、Combiner(作业的合并器) 和 Reducer 类
        conf.setMapperClass(Map.class);
        conf.setCombinerClass(Reduce.class);
        conf.setReducerClass(Reduce.class);

        // 设置输入和输出格式
        conf.setInputFormat(TextInputFormat.class);
        conf.setOutputFormat(TextOutputFormat.class);

        // 设置输入和输出路径
        FileInputFormat.setInputPaths(conf, new Path(args[0])); // 输入路径
        FileOutputFormat.setOutputPath(conf, new Path(args[1])); // 输出路径

        // 运行作业,并获取运行时作业对象
        RunningJob job = JobClient.runJob(conf);

        // 获取计数器
        Counters counters = job.getCounters();
        // 输出单词总数
        Counter counter = counters.findCounter(Task.Counter.REDUCE_OUTPUT_RECORDS);
        System.out.println("Total Words Count: " + counter.getValue());
    }
}

  • Mapper 类负责将输入文本拆分成单词,并输出每个单词的初始计数为 1。
  • Reducer 类接收 Mapper 的输出,将相同单词的计数合并,并输出每个单词的总计数。
  • 主函数负责配置作业参数,如输入路径、输出路径、Mapper 类、Reducer 类等,并运行作业。然后,它获取作业的计数器,用于统计单词总数。
项目打包

在这里插入图片描述

在这里插入图片描述

将生成的jar包上传到集群中

在这里插入图片描述

[root@master ~]# cd /usr/local
[root@master local]# ll
总用量 8
drwxr-xr-x.  2 root  root     6 42 16:54 demo
drwxr-xr-x. 11  1000  1000  227 326 16:21 hadoop-3.3.1
-rw-r--r--.  1 root  root  5599 58 14:49 hadoopdemo2-1.0-SNAPSHOT.jar
drwxr-xr-x.  8 10143 10143  273 48 2021 jdk1.8.0_291

运行
[root@master local]# hadoop jar hadoopdemo2-1.0-SNAPSHOT.jar com.sin.demo.WordCount /input/input.txt /output
2024-05-08 14:50:25,570 INFO client.DefaultNoHARMFailoverProxyProvider: Connecting to ResourceManager at master/192.168.226.140:8032
2024-05-08 14:50:25,939 INFO client.DefaultNoHARMFailoverProxyProvider: Connecting to ResourceManager at master/192.168.226.140:8032
2024-05-08 14:50:26,500 WARN mapreduce.JobResourceUploader: Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.
2024-05-08 14:50:26,545 INFO mapreduce.JobResourceUploader: Disabling Erasure Coding for path: /tmp/hadoop-yarn/staging/root/.staging/job_1715142816014_0002
2024-05-08 14:50:26,984 INFO mapred.FileInputFormat: Total input files to process : 1
2024-05-08 14:50:27,118 INFO mapreduce.JobSubmitter: number of splits:2
2024-05-08 14:50:27,434 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1715142816014_0002
2024-05-08 14:50:27,434 INFO mapreduce.JobSubmitter: Executing with tokens: []
2024-05-08 14:50:27,711 INFO conf.Configuration: resource-types.xml not found
2024-05-08 14:50:27,711 INFO resource.ResourceUtils: Unable to find 'resource-types.xml'.
2024-05-08 14:50:27,849 INFO impl.YarnClientImpl: Submitted application application_1715142816014_0002
2024-05-08 14:50:27,941 INFO mapreduce.Job: The url to track the job: http://master:8088/proxy/application_1715142816014_0002/
2024-05-08 14:50:27,950 INFO mapreduce.Job: Running job: job_1715142816014_0002
2024-05-08 14:50:37,120 INFO mapreduce.Job: Job job_1715142816014_0002 running in uber mode : false
2024-05-08 14:50:37,121 INFO mapreduce.Job:  map 0% reduce 0%
2024-05-08 14:50:49,264 INFO mapreduce.Job:  map 100% reduce 0%
2024-05-08 14:50:55,388 INFO mapreduce.Job:  map 100% reduce 100%
2024-05-08 14:50:55,398 INFO mapreduce.Job: Job job_1715142816014_0002 completed successfully
2024-05-08 14:50:55,500 INFO mapreduce.Job: Counters: 54
        File System Counters
                FILE: Number of bytes read=147
                FILE: Number of bytes written=818984
                FILE: Number of read operations=0
                FILE: Number of large read operations=0
                FILE: Number of write operations=0
                HDFS: Number of bytes read=292
                HDFS: Number of bytes written=87
                HDFS: Number of read operations=11
                HDFS: Number of large read operations=0
                HDFS: Number of write operations=2
                HDFS: Number of bytes read erasure-coded=0
        Job Counters
                Launched map tasks=2
                Launched reduce tasks=1
                Data-local map tasks=2
                Total time spent by all maps in occupied slots (ms)=19490
                Total time spent by all reduces in occupied slots (ms)=7972
                Total time spent by all map tasks (ms)=19490
                Total time spent by all reduce tasks (ms)=3986
                Total vcore-milliseconds taken by all map tasks=19490
                Total vcore-milliseconds taken by all reduce tasks=3986
                Total megabyte-milliseconds taken by all map tasks=19957760
                Total megabyte-milliseconds taken by all reduce tasks=8163328
        Map-Reduce Framework
                Map input records=5
                Map output records=13
                Map output bytes=127
                Map output materialized bytes=153
                Input split bytes=172
                Combine input records=13
                Combine output records=12
                Reduce input groups=11
                Reduce shuffle bytes=153
                Reduce input records=12
                Reduce output records=11
                Spilled Records=24
                Shuffled Maps =2
                Failed Shuffles=0
                Merged Map outputs=2
                GC time elapsed (ms)=498
                CPU time spent (ms)=2780
                Physical memory (bytes) snapshot=527880192
                Virtual memory (bytes) snapshot=9078263808
                Total committed heap usage (bytes)=266428416
                Peak Map Physical memory (bytes)=212107264
                Peak Map Virtual memory (bytes)=2738208768
                Peak Reduce Physical memory (bytes)=106110976
                Peak Reduce Virtual memory (bytes)=3605901312
        Shuffle Errors
                BAD_ID=0
                CONNECTION=0
                IO_ERROR=0
                WRONG_LENGTH=0
                WRONG_MAP=0
                WRONG_REDUCE=0
        File Input Format Counters
                Bytes Read=120
        File Output Format Counters
                Bytes Written=87
Total Words Count: 11
  • hadoop jar: 这是执行Hadoop作业的命令前缀,表示要运行一个打包成可执行JAR文件的Hadoop作业。
  • hadoopdemo2-1.0-SNAPSHOT.jar: 这是要执行的Java可执行JAR文件的名称,该JAR文件包含了要运行的MapReduce作业的代码和依赖项。
  • com.sin.demo.WordCount: 这是包含MapReduce作业实现的主类的完全限定名称。在这个例子中,主类是WordCount类,它实现了MapReduce作业的逻辑。
  • /input/input.txt: 这是输入文件的路径,MapReduce作业将会从这个文件中读取数据进行处理。在这里,输入文件是input.txt,位于Hadoop文件系统中的/input目录下。
  • /output: 这是输出目录的路径,MapReduce作业将会把处理结果输出到这个目录中。在这里,输出目录是/output,结果文件将会以默认的分区格式存储在这个目录下。
查看输出结果

在这里插入图片描述

# 被处理的文件
[root@master local]# hadoop fs -cat /input/input.txt
Hello world
Hello GPT
World of programming
Programming is fun
Fun with GPT
# 处理结束的文件
[root@master local]# hadoop fs -cat /output/part-00000
Fun     1
GPT     2
Hello   2
Programming     1
World   1
fun     1
is      1
of      1
programming     1
with    1
world   1

练习案例

超市在1月份的购买记录

2024-01-02,商品A,1
2024-01-02,商品A,2
2024-01-10,商品C,1
2024-01-15,商品D,3
2024-01-18,商品E,2
2024-01-20,商品F,4
2024-01-25,商品G,1
2024-01-20,商品H,2
2024-02-01,商品I,3
2024-02-05,商品J,1
2024-02-10,商品K,2
2024-02-15,商品L,1
2024-03-02,商品A,4
2024-03-05,商品N,1
2024-03-10,商品O,2
2024-03-15,商品P,3
2024-04-02,商品Q,1
2024-04-05,商品R,2
2024-04-10,商品S,4
2024-04-10,商品T,1
package com.sin.demo;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.mapreduce.Counter;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;

public class WordCount {

    public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
        private final static IntWritable one = new IntWritable(1); // 记录出现次数
        private Text word = new Text(); // 单词

        public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
            // 将输入数据转换为字符串
            String line = value.toString();
            // 将每一个字符串之间添加空格
            StringTokenizer tokenizer = new StringTokenizer(line);
            // 遍历数据
            while (tokenizer.hasMoreTokens()) {
                // 将字符串存储到Text文本类型中
                String[] parts = tokenizer.nextToken().split(","); // 假设数据以逗号分隔
                String date = parts[0]; // 假设日期在数据的第一个位置
                // 如果日期是1月份,则进行统计
                if (date.startsWith("2024-01")) {
                    word.set("purchase_in_january"); // 设置单词为购买次数在1月份
                    // 输出单词及其出现次数
                    output.collect(word, one);
                }
            }
        }
    }

    public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {

        public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
            // 记录字符串出现的次数
            int sum = 0;
            // 遍历字符串
            while (values.hasNext()) {
                sum += values.next().get(); // 累加相同单词的出现次数
            }
            // 输出字符串及其总次数
            output.collect(key, new IntWritable(sum));
        }
    }

    public static void main(String[] args) throws Exception {
        JobConf conf = new JobConf(WordCount.class);
        // 设置作业名称
        conf.setJobName("wordcount");

        // 设置输出键和值的类型
        conf.setOutputKeyClass(Text.class);
        conf.setOutputValueClass(IntWritable.class);

        // 设置 Mapper、Combiner 和 Reducer 类
        conf.setMapperClass(Map.class);
        conf.setCombinerClass(Reduce.class);
        conf.setReducerClass(Reduce.class);

        // 设置输入和输出格式
        conf.setInputFormat(TextInputFormat.class);
        conf.setOutputFormat(TextOutputFormat.class);

        // 设置输入和输出路径
        FileInputFormat.setInputPaths(conf, new Path(args[0])); // 输入路径
        FileOutputFormat.setOutputPath(conf, new Path(args[1])); // 输出路径

        // 运行作业,并获取运行时作业对象
        RunningJob job = JobClient.runJob(conf);

        // 获取计数器
        Counters counters = job.getCounters();
        // 输出购买次数
        Counter counter = counters.findCounter(Task.Counter.REDUCE_OUTPUT_RECORDS);
        System.out.println("Total Purchase Count in January: " + counter.getValue());
    }
}
上传并测试
[root@master local]# hadoop jar hadoopdemo2-1.0-SNAPSHOT.jar com.sin.demo.WordCount /input/demosupermarket.txt /output1
2024-05-08 15:06:51,710 INFO client.DefaultNoHARMFailoverProxyProvider: Connecting to ResourceManager at master/192.168.226.140:8032
2024-05-08 15:06:51,965 INFO client.DefaultNoHARMFailoverProxyProvider: Connecting to ResourceManager at master/192.168.226.140:8032
2024-05-08 15:06:52,438 WARN mapreduce.JobResourceUploader: Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.
2024-05-08 15:06:52,483 INFO mapreduce.JobResourceUploader: Disabling Erasure Coding for path: /tmp/hadoop-yarn/staging/root/.staging/job_1715142816014_0003
2024-05-08 15:06:52,820 INFO mapred.FileInputFormat: Total input files to process : 1
2024-05-08 15:06:52,924 INFO mapreduce.JobSubmitter: number of splits:2
2024-05-08 15:06:53,216 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1715142816014_0003
2024-05-08 15:06:53,216 INFO mapreduce.JobSubmitter: Executing with tokens: []
2024-05-08 15:06:53,428 INFO conf.Configuration: resource-types.xml not found
2024-05-08 15:06:53,428 INFO resource.ResourceUtils: Unable to find 'resource-types.xml'.
2024-05-08 15:06:53,550 INFO impl.YarnClientImpl: Submitted application application_1715142816014_0003
2024-05-08 15:06:53,592 INFO mapreduce.Job: The url to track the job: http://master:8088/proxy/application_1715142816014_0003/
2024-05-08 15:06:53,593 INFO mapreduce.Job: Running job: job_1715142816014_0003
2024-05-08 15:07:02,767 INFO mapreduce.Job: Job job_1715142816014_0003 running in uber mode : false
2024-05-08 15:07:02,768 INFO mapreduce.Job:  map 0% reduce 0%
2024-05-08 15:07:12,064 INFO mapreduce.Job:  map 50% reduce 0%
2024-05-08 15:07:13,070 INFO mapreduce.Job:  map 100% reduce 0%
2024-05-08 15:07:19,193 INFO mapreduce.Job:  map 100% reduce 100%
2024-05-08 15:07:19,203 INFO mapreduce.Job: Job job_1715142816014_0003 completed successfully
2024-05-08 15:07:19,305 INFO mapreduce.Job: Counters: 54
        File System Counters
                FILE: Number of bytes read=546
                FILE: Number of bytes written=819815
                FILE: Number of read operations=0
                FILE: Number of large read operations=0
                FILE: Number of write operations=0
                HDFS: Number of bytes read=822
                HDFS: Number of bytes written=460
                HDFS: Number of read operations=11
                HDFS: Number of large read operations=0
                HDFS: Number of write operations=2
                HDFS: Number of bytes read erasure-coded=0
        Job Counters
                Launched map tasks=2
                Launched reduce tasks=1
                Data-local map tasks=2
                Total time spent by all maps in occupied slots (ms)=15391
                Total time spent by all reduces in occupied slots (ms)=8482
                Total time spent by all map tasks (ms)=15391
                Total time spent by all reduce tasks (ms)=4241
                Total vcore-milliseconds taken by all map tasks=15391
                Total vcore-milliseconds taken by all reduce tasks=4241
                Total megabyte-milliseconds taken by all map tasks=15760384
                Total megabyte-milliseconds taken by all reduce tasks=8685568
        Map-Reduce Framework
                Map input records=20
                Map output records=20
                Map output bytes=500
                Map output materialized bytes=552
                Input split bytes=192
                Combine input records=20
                Combine output records=20
                Reduce input groups=20
                Reduce shuffle bytes=552
                Reduce input records=20
                Reduce output records=20
                Spilled Records=40
                Shuffled Maps =2
                Failed Shuffles=0
                Merged Map outputs=2
                GC time elapsed (ms)=393
                CPU time spent (ms)=1710
                Physical memory (bytes) snapshot=494489600
                Virtual memory (bytes) snapshot=9074069504
                Total committed heap usage (bytes)=266719232
                Peak Map Physical memory (bytes)=193802240
                Peak Map Virtual memory (bytes)=2734153728
                Peak Reduce Physical memory (bytes)=112553984
                Peak Reduce Virtual memory (bytes)=3605762048
        Shuffle Errors
                BAD_ID=0
                CONNECTION=0
                IO_ERROR=0
                WRONG_LENGTH=0
                WRONG_MAP=0
                WRONG_REDUCE=0
        File Input Format Counters
                Bytes Read=630
        File Output Format Counters
                Bytes Written=460
Total Words Count: 20

查看结果
[root@master local]# hadoop fs -cat /output3/part-00000
2024-01-02,商品A,1      1
2024-01-02,商品A,2      1
2024-01-10,商品C,1      1
2024-01-15,商品D,3      1
2024-01-18,商品E,2      1
2024-01-20,商品F,4      1
2024-01-20,商品H,2      1
2024-01-25,商品G,1      1
2024-02-01,商品I,3      1
2024-02-05,商品J,1      1
2024-02-10,商品K,2      1
2024-02-15,商品L,1      1
2024-03-02,商品A,4      1
2024-03-05,商品N,1      1
2024-03-10,商品O,2      1
2024-03-15,商品P,3      1
2024-04-02,商品Q,1      1
2024-04-05,商品R,2      1
2024-04-10,商品S,4      1
2024-04-10,商品T,1      1
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MapReduce编程中,倒排索引是一种常见的应用案例。倒排索引(Inverted index)是一种索引方法,用于存储某个单词在一个文档或一组文档中的位置映射。它是文档检索系统中最常用的数据结构。 在实现倒排索引的MapReduce程序中,首先需要设置MapReduce工作任务的相关参数,比如输入路径和输出路径。然后,需要编写自定义的Mapper类,将文本中的单词按照空格进行切割,并将“单词:文档名称”作为key,单词次数作为value输出。接着,在Map阶段的输出结果形式基础上,可以编写自定义的Combiner类,对每个文档的单词进行词频统计。 具体实现过程中,可以使用Eclipse等开发工具打开项目,并按照指定的路径和格式进行输入和输出。在Mapper类中,可以使用split函数对文本进行切割,并使用context.write函数将结果输出。在Combiner类中,可以对每个文档的单词进行统计,并输出结果。最后,通过在MapReduce程序中指定输入路径和输出路径,运行程序即可得到倒排索引的结果。 总结起来,实现倒排索引的MapReduce程序包括设置任务参数、编写Mapper类、编写Combiner类,并按照指定的输入和输出路径运行程序。通过这样的实现,可以将文档中的单词按照索引形式进行存储,方便后续的全文搜索等操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆卿之

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值