hadoop中的wordcount

Hadoop生态


HDFS

HDFS写数据流程
HDFS写数据
(1)客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件,NameNode 检查目标文件是否已存在,父目录是否存在
(2)NameNode 返回是否可以上传,若不能,返回异常
(3)确定可以上传,客户端请求第一个 block 上传到哪几个 datanode服务器上
(4)NameNode 返回3个 datanode 节点,假定分别为dn1、dn2、dn3
(5)客户端通过 FSDataOutputStream 模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成
(6)dn1、dn2、dn3逐级应答客户端
(7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以 packet(64KB) 为单位,dn1收到一个packet 就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答
(8)当一个block传输完成之后,客户端再次请求 NameNode 上传第二个block的服务器(重复执行3-7步)


HDFS读数据流程

在这里插入图片描述
(1)首先调用FileSystem.open()方法,获取到 DistributedFileSystem 实例
(2)DistributedFileSystem 向 Namenode 发起 PRC(远程过程调用)请求获得文件的开始部分或全部 block 列表,对于每个返回的块,都包含块所在的 DataNode 地址。这些 DataNode 会按照 Hadoop 定义的集群拓扑结构得出客户端的距离,然后再进行排序。如果客户端本身就是一个DataNode,那么他将从本地读取文件
(3) DistributedFileSystem 会向客户端 client 返回一个支持文件定位的输入流对象 FSDataInputStream,用于客户端读取数据。FSDataInputStream 包含一个 DFSInputStream 对象,这个对象用来管理 DataNode 和 NameNode 之间的 I/O
(4)客户端调用read()方法,DFSInputStream 就会找出离客户端最近的datanode并连接datanode
(5)DFSInputStream 对象中包含文件开始部分的数据块所在的DataNode地址,首先它会连接包含文件第一个块最近的DataNode。随后,在数据流中重复调用read()函数,直到这个块全部读完为止。如果第一个block块的数据读完,就会关闭指向第一个block块的datanode连接,接着读取下一个block块
(6)如果第一批block都读完了,DFSInputStream 就回去NameNode拿下一批blocks的location,然后继续读,如果所有的block块都读完,这时就会关闭掉所有的流


MapReduce

在这里插入图片描述

(1)map task进程开始,利用客户端指定的inputformat来读取数据
(2)利用RecordReader,调用read()方法,一次读一行,每一行就是一份文件片
(3)行偏移量为k,每行的内容为v,生成键值对(k,v)
(4)获得的键值对(k,v)经过Mapper的map方法逻辑处理形成新的键值对map(k,v),此时k是单词,v是个数
通过context.write()方法把map(k,v)输出到OutputCollector收集器;
(5)OutputCollector把键值对map(k,v)写入到环形缓冲区中,此时shuffle开始。环形缓冲区默认大小为100M,环形缓冲区里面的数据到80%时,就会溢出
(6)溢出前需要对环形缓冲区里的键hash出一个partition值,根据partition分区,相同分区内根据键进行排序
(7)此时如果写了Combiner方法,会把同一个key的键值对合并在一起,生成有分区且相同分区内有序的大文件。这个合并的目的是为了减少网络传输。
(8)如果没有写Combiner方法,环形缓冲区开始溢出到map task本地磁盘,此时是有分区且分区内有序的小文件,如果数据量过大,会溢出多个文件;
(9)小文件会被merge归并排序成有分区且分区内有序的大文件,此时map task结束
(10)reduce任务开始,不同的reducetask根据分区号,去不同的maptask中拷贝与自己相同分区号的文件到reduce task本地磁盘
(11)各个reduce task把拷贝过来的与自己同一分区号的文件进行merge归并排序成一个大文件,文件内部的键值对根据键排序,此时shuffle过程结束
(12)GroupingComparator(k,nextk)对大文件里面的数据根据k进行分组,从文件中每次取出一组键值对(k,values),
经过Reducer的reduce方法逻辑处理形成新的键值对reduce(k,v),此时k是单词,v是这个单词的个数
(13)调用context.write(k,v)方法写入到OutPutFormat里,然后将数据结果落盘


WordMapper类

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class WordMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
    
    
    private Text word = new Text();
    private IntWritable count = new IntWritable(1);

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    
    
        String[] words = value.toString().trim()
                .replaceAll(",|\\.|!|\\?|;|\"", "").split(" ");
        for (String word : words) {
    
    
            this.word.set(word);
            context.write(this.word,count);
        }
    }
}

WordReducer类

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class WordReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
    
    
    private IntWritable count = new IntWritable();

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
    
    
        int sum = 0;
        for (IntWritable value : values) {
    
    
            sum += value.get();
        }
        count.set(sum);
        context.write(key,count);
    }
}

WordPartitioner类

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

public class WordPatritioner extends Partitioner<Text, IntWritable> {
    
    
    @Override
    public int getPartition(Text text, IntWritable intWritable, int numberReduceTasks) {
    
    
        return text.toString().length()%numberReduceTasks;
    }
}

启动类

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class WordTest {
    
    
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
    
    
        //创建hdfs访问路径配置信息
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.247.130:9000");

        //创建mapreduce计算任务
        Job job = Job.getInstance(config,"wordCount");
        //设置主类,定位外部jar资源
        job.setJarByClass(WordTest.class);
        //设置任务数:和文件分片数和所存储的DN数有关
        job.setNumReduceTasks(2);
        //设置分区器Partitioner
        job.setPartitionerClass(WordPatritioner.class);
        //设置Combiner
        job.setCombinerClass(WordReducer.class);

        //设置Mapper
        job.setMapperClass(WordMapper.class);
        //设置Reducer
        job.setReducerClass(WordReducer.class);

        //设置Mapper的输出键值类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        //设置Reducer的输出键值类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //设置hdfs输入文件绑定job
        FileInputFormat.setInputPaths(job,new Path("/kb10/Pollyanna.txt"));
        FileOutputFormat.setOutputPath(job,new Path("/kb10/wc01"));

        System.out.println(job.waitForCompletion(true));
    }
}

将测试文章放入hdfs中

[root@single ~]# hdfs dfs -put Pollyanna.txt /kb10/

在这里插入图片描述
Java中运行启动类WordTest

2020-11-22 21:06:51,283 INFO [org.apache.hadoop.conf.Configuration.deprecation] - session.id is deprecated. Instead, use dfs.metrics.session-id
2020-11-22 21:06:51,284 INFO [org.apache.hadoop.metrics.jvm.JvmMetrics] - Initializing JVM Metrics with processName=JobTracker, sessionId=
2020-11-22 21:07:00,797 WARN [org.apache.hadoop.mapreduce.JobSubmitter] - Submitting tokens for job: job_local188587393_0001
[org.apache.hadoop.mapred.LocalJobRunner] - reduce task executor complete.
...
...
...
2020-11-22 21:07:02,037 INFO [org.apache.hadoop.mapreduce.Job] - Job job_local188587393_0001 running in uber mode : false
2020-11-22 21:07:02,038 INFO [org.apache.hadoop.mapreduce.Job] -  map 100% reduce 100%
2020-11-22 21:07:02,038 INFO [org.apache.hadoop.mapreduce.Job] - Job job_local188587393_0001 completed successfully
2020-11-22 21:07:02,053 INFO [org.apache.hadoop.mapreduce.Job] - Counters: 35
	File System Counters
		FILE: Number of bytes read=37065
		FILE: Number of bytes written=1359678
		FILE: Number of read operations=0
		FILE: Number of large read operations=0
		FILE: Number of write operations=0
		HDFS: Number of bytes read=30364
		HDFS: Number of bytes written=9124
		HDFS: Number of read operations=38
		HDFS: Number of large read operations=0
		HDFS: Number of write operations=16
	Map-Reduce Framework
		Map input records=35
		Map output records=1365
		Map output bytes=12733
		Map output materialized bytes=6687
		Input split bytes=111
		Combine input records=1365
		Combine output records=528
		Reduce input groups=528
		Reduce shuffle bytes=6687
		Reduce input records=528
		Reduce output records=528
		Spilled Records=1056
		Shuffled Maps =3
		Failed Shuffles=0
		Merged Map outputs=3
		GC time elapsed (ms)=0
		Total committed heap usage (bytes)=1025507328
	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=7591
	File Output Format Counters 
		Bytes Written=4580
true

查看hdfs中的数据结果
在这里插入图片描述
因为指定了3个job,所以生成了三个文件
在这里插入图片描述
查看wordcount结果

[root@single ~]# hdfs dfs -cat /kb10/wc01/part-r-*

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_48482704/article/details/109710672
今日推荐