大数据修炼之hadoop--MapReduce

2024-09-02 12:32
文章标签 数据 hadoop 修炼 mapreduce

本文主要是介绍大数据修炼之hadoop--MapReduce,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 定义
  • 概念
  • 流程
  • 支持的数据类型
  • demo
  • 切片策略
    • FileInputFormat
  • 片与块的关系
  • 提交流程
  • 关键设置
  • Job提交流程阶段总结
    • 准备
    • 提交

定义

MapReduce最早是由谷歌公司研究提出的一种面向大规模数据处理的并行计算模型和方法。
特点:
MapReduce是一个基于集群的高性能并行计算平台。
MapReduce是一个并行计算与运行软件框架。
MapReduce是一个并行程序设计模型与方法。

易于编程,良好的扩展性,高容错性,适合PB级别以上的海量数据的离线处理
但是同时,不适合实时计算,不擅长流式计算,不擅长DAG计算(程序依赖)

概念

Job(任务): 一个MR程序
MRAppMaster(MR任务的主节点):一个Job在运行是,会先启动一个进程,负责Job执行过程的监控,容错,申请资源,提交task
Task(任务):计算
Map:切分。 将输入数据切分成若干小部分,每个部分为1片split,每片数据交给一个task进行计算(MapTask)
Reduce: MapTask的汇总

常用组件:
Mapper
Reducer
InputFormat 输入目录的文件格式。 普通文件:FileInputFormat , SequeceFileInput(hadoop格式),DBInputFormat(数据库的格式)
OutputFormat 类上
RecordWriter 记录写出其 结果以什么格式,写出到文件中
Partitioner 分区器

流程

MapReduce中,Map阶段处理的数据如何传递给Reduce阶段,是整个MapReduce框架中最关键的一个流程,这个流程就叫Shuffle。它的核心机制包括数据分区、排序和缓存等。
在这里插入图片描述

支持的数据类型

(1)BooleanWritable:标准布尔型数值。
(2)ByteWritable:单字节数值。
(3)DoubleWritable:双字节数。
(4)FloatWritable:浮点数。
(5)IntWritable:整型数。
(6)LongWritable:长整型数。
(7)Text:使用UTF8格式存储的文本。
(8)NullWritable:当<key,value>中的key或value为空时使用。
(9)ArrayWritable:存储属于Writable类型的值数组(要使用ArrayWritable类型作为Reduce输入的value类型,需要创建ArrayWritable的子类来指定存储在其中的Writable值的类型)。

运行最新版hadoop的mapreduce的时候经常会有各种报错,最好是有linux环境可以用。windows环境下设置HADOOP_HOME,并把wintils放在bin目录下:
https://github.com/steveloughran/winutils

demo

maven

 <dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-common</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-hdfs</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-mapreduce-client-core</artifactId><version>3.2.0</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>

code:

public class MyDriver {public static final Configuration configuration = new Configuration();static {
//        configuration.set("fs.defaultFS", "hdfs://192.168.31.101:9000");System.setProperty("HADOOP_USER_NAME", "hadoop");
//        System.setProperty("HADOOP_HOME", "D:\\tools\\hadoop-3.3.0");}public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {remortJob();
//        localJob();}private static void remortJob() throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {System.setProperty("HADOOP_HOME", "D:\\tools\\hadoop-3.3.0");Path inputPath=new Path("/wcinput/logs");Path outputPath=new Path("/wcoutput/test");configuration.set("fs.defaultFS","hdfs://192.168.31.101:9000");configuration.set("fs.defaultFS","hdfs://192.168.31.101:9000");FileSystem fs=FileSystem.get(new URI("hdfs://192.168.31.101:9000"),configuration,"root");if (fs.exists(outputPath)) {fs.delete(outputPath, true);}
//        创建jobJob job=Job.getInstance(configuration);job.setJobName("wordcount test");
//        设置jobjob.setMapperClass(MyMapper.class);job.setReducerClass(MyReducer.class);
//            准备序列化器job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);//            输入输出目录FileInputFormat.setInputPaths(job,inputPath);FileOutputFormat.setOutputPath(job,outputPath);
//        运行jobjob.waitForCompletion(true);}private static void localJob() throws IOException, InterruptedException, ClassNotFoundException {System.setProperty("HADOOP_HOME", "D:\\tools\\hadoop-3.3.0");Path inputPath=new Path("d:/mrinput/");Path outputPath=new Path("d:/mroutput/wd");FileSystem fs=FileSystem.get(configuration);
//        创建jobJob job=Job.getInstance(configuration);job.setJobName("wordcount test");
//        设置jobjob.setMapperClass(MyMapper.class);job.setReducerClass(MyReducer.class);
//            准备序列化器job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);//            输入输出目录FileInputFormat.setInputPaths(job,inputPath);FileOutputFormat.setOutputPath(job,outputPath);
//        运行jobjob.waitForCompletion(true);}
}public class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {private Text outKey=new Text();private IntWritable outValue=new IntWritable(1);/*** 每个 keyin  valuein 执行一次* 每个 keyvalue都转成(word,1)* @param key* @param value* @param context* @throws IOException* @throws InterruptedException*/@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//        super.map(key, value, context);System.out.println(" key:"+key +"  value:"+value);String[] split = value.toString().split("\t");for (String word :split) {outKey.set(word);context.write(outKey,outValue);}}
}public class MyReducer extends Reducer<Text, IntWritable,Text,IntWritable> {private IntWritable outValue;@Overrideprotected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
//        super.reduce(key, values, context);int sum=0;for (IntWritable item :values) {sum += item.get();}outValue = new IntWritable(sum);context.write(key,outValue);}
}

InputFormat的作用:

  1. 验证输入目录中文件格式,是否符合当前Job的要求
  2. 生产切片,每个切片都会交给一个MapTask处理
  3. 提供RecordReader,由RR从切片中读取记录,交给Mapper处理。

方法 List getSplits: 切片
RecordReader<K,V> createRecordReader: 创建RR

默认使用的是TextInputFormat , LineRecordReader

切片策略

TextInputFormat:
常用于输入目录中全是文本文件
RecordReader: LineRecordReader 一次处理一行,将一行内容偏移量作为key,内容value

NLineInputFormat:
切分n行,执行逻辑复杂情况

KeyValueTextInputFormat:
键值对格式
CombineTextInputText:
多个小文件

FileInputFormat

 public List<InputSplit> getSplits(JobContext job) throws IOException {StopWatch sw = new StopWatch().start();long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));// getFormatMinSplitSize  其实是1,getMinSplitSize 是取配置 mapreduce.input.fileinputformat.split.maxsizelong maxSize = getMaxSplitSize(job);   //mapreduce.input.fileinputformat.split.maxsize// generate splitsList<InputSplit> splits = new ArrayList<InputSplit>();List<FileStatus> files = listStatus(job);  // 输入目录所有文件的状态信息boolean ignoreDirs = !getInputDirRecursive(job)&& job.getConfiguration().getBoolean(INPUT_DIR_NONRECURSIVE_IGNORE_SUBDIRS, false);for (FileStatus file: files) {if (ignoreDirs && file.isDirectory()) {continue;}Path path = file.getPath();long length = file.getLen();if (length != 0) {BlockLocation[] blkLocations;if (file instanceof LocatedFileStatus) {blkLocations = ((LocatedFileStatus) file).getBlockLocations();} else {FileSystem fs = path.getFileSystem(job.getConfiguration());blkLocations = fs.getFileBlockLocations(file, 0, length);}if (isSplitable(job, path)) {//  判断方法与实现类相关,各个类自己实现,默认truelong blockSize = file.getBlockSize();long splitSize = computeSplitSize(blockSize, minSize, maxSize);long bytesRemaining = length; // 循环切片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;}if (bytesRemaining != 0) {int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);splits.add(makeSplit(path, length-bytesRemaining, bytesRemaining,blkLocations[blkIndex].getHosts(),blkLocations[blkIndex].getCachedHosts()));}} else { // not splitable  不可切,直接传入文件if (LOG.isDebugEnabled()) {// Log only if the file is big enough to be splittedif (length > Math.min(file.getBlockSize(), minSize)) {LOG.debug("File is not splittable so no parallelization "+ "is possible: " + file.getPath());}}splits.add(makeSplit(path, 0, length, blkLocations[0].getHosts(),blkLocations[0].getCachedHosts()));}} else { //Create empty hosts array for zero length filessplits.add(makeSplit(path, 0, length, new String[0]));}}// Save the number of input files for metrics/loadgenjob.getConfiguration().setLong(NUM_INPUT_FILES, files.size());sw.stop();if (LOG.isDebugEnabled()) {LOG.debug("Total # of splits generated by getSplits: " + splits.size()+ ", TimeTaken: " + sw.now(TimeUnit.MILLISECONDS));}return splits;}

片与块的关系

默认的片大小是文件的块大小,文件默认128M
片: InputSplit 计算MR时进行切片,临时的逻辑区,与输入格式相关
块:Block HDFS的存储单位,实际物理存在

建议,片大小=块大小。减少磁盘IO,网络IO

提交流程

 public boolean waitForCompletion(boolean verbose) throws IOException, InterruptedException,ClassNotFoundException {if (state == JobState.DEFINE) {submit();}if (verbose) {monitorAndPrintJob();} else {// get the completion poll interval from the client.int completionPollIntervalMillis = Job.getCompletionPollInterval(cluster.getConf());while (!isComplete()) {try {Thread.sleep(completionPollIntervalMillis);} catch (InterruptedException ie) {}}}return isSuccessful();}
 public void submit() throws IOException, InterruptedException, ClassNotFoundException {ensureState(JobState.DEFINE);setUseNewAPI();connect();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);}});state = JobState.RUNNING;LOG.info("The url to track the job: " + getTrackingURL());}

关键设置

MapTask数量,认为设置无效,只能通过切片的方式设置,MapTask取决于切片数。

Job提交流程阶段总结

准备

运行job.waitForCompletion(),生成一下信息
job.split 当前job的切片信息,有几个切片对象
job.splitmetainfo 切片对象的属性信息
job.xml job的属性配置

提交

本地模式:LocalJobRunner提交,创建LocalJobRunner.Job()
Map阶段: 线程池,提交多个MapTaskRunnable
每个MapTaskRunnable线程上,实例化一个MapTask对象
每个MapTask对象实例化一个Mapper
线程运行结束,在线程的作业目录中生成file.out文件,报错MapTask输出的所有Key-value
map:使用RR将切片中的数据读入到Mapper.map() context.write(key,value)
Reduce阶段:
线程池提交多个ReduceTaskRunnable
每个ReduceTask对象,实例化一个Reducer, reducer.run()
线程运行结束,在输出目录中生成,part-r-000x文件,保存ReduceTask输出的所有Key-value
copy: shuffle线程拷贝MapTask指定的分区数据
sort:将拷贝的所有分区数据汇总后,排序
reduce:排好序的数据,进行 合并

这篇关于大数据修炼之hadoop--MapReduce的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129958

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi