Hadoop生态圈(二十二)- MapReduce并行度机制

原文地址:https://program-park.github.io/2022/02/04/hadoop_26/

1. MapTask并行度机制

1.1 概念

  MapTask 的并行度指的是map阶段有多少个并行的task共同处理任务。map 阶段的任务处理并行度,势必影响到整个 Job 的处理速度。

  • 一个 Job 的 Map 阶段并行度由客户端在提交 Job 时的切片数决定;
  • 数据块:Block 是 HDFS 物理上把数据分成一块一块。数据块是 HDFS 存储数据单位;
  • 数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是 MapReduce 程序计算输入数据的单位,一个切片会对应启动一个 MapTask;

1.2 逻辑规划

  • MapTask 并行度的决定机制叫做逻辑规划
  • 客户端提交Job之前会对待处理数据进行逻辑切片,形成逻辑规划文件
  • 逻辑切片机制由 FileInputFormat 实现类的getSplits()方法完成;
  • 逻辑规划结果写入规划文件(job.split),在客户端提交 Job 之前,把规划文件提交到任务准备区,供后续使用;
  • 每个逻辑切片最终对应启动一个 MapTask;

1.3 逻辑规划规则

  • FileInputFormat中默认的切片机制:
    • 简单地按照文件的内容长度进行切片;
    • 切片大小,默认等于 block 大小,而 block 大小默认为 128M;
    • 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片;
# 比如待处理数据有两个文件
file1.txt 320M
file2.txt 10M
# 经过FileInputFormat的切片机制运算后,形成切片信息如下:
file1.txt.split1	0M~128M
file1.txt.split2	128M~256M
file1.txt.split3	256M~320M
file2.txt.split1	0M~10M

1.4 逻辑切片相关参数

  在 FileInputFormat 中,计算切片大小的逻辑:Math.max(minSize, Math.min(maxSize, blockSize));
  切片主要由这几个值来运算决定:

  • minsize(切片最小值),默认值:1
    • 配置参数: mapreduce.input.fileinputformat.split.minsize=1
    • 参数调的比 blockSize 大,则可以让切片变得比 blockSize 还大;
  • maxsize,默认值:Long.MAXValue
    • 配置参数:mapreduce.input.fileinputformat.split.maxsize=Long.MAXValue
    • 参数如果调的比 blockSize 小,则会让切片变小,而且就等于配置的这个参数的值;

  因此,默认情况下,split size=block size,在 hadoop 2.x 中为 128M。
  但是,不论怎么调参数,都不能让多个小文件 “划入” 一个 split。
  另外,当bytesRemaining/splitSize > 1.1不满足的话,那么最后所有剩余的会作为一个切片。从而不会形成例如 129M 文件规划成两个切片的局面。

2. ReduceTask并行度机制

  • Reducetask 并行度同样影响整个 job 的执行并发度和执行效率,与 maptask 的并发数由切片数决定不同,Reducetask 数量的决定是可以直接手动设置job.setNumReduceTasks(4)
  • 注意 Reducetask 数量并不是任意设置,还要考虑业务逻辑需求,有些情况下,需要计算全局汇总结果,就只能有 1个 Reducetask;
  • 如果数据分布不均匀,就有可能在 reduce 阶段产生数据倾斜;

3. CombineTextInputFormat

3.1 TextInputFormat

  在运行 MapReduce 程序时,输入的文件格式包括:基于行的日志文件、二进制格式文件、数据库表等。针对不同的数据类型,FileInputFormat 有不同的接口实现类:TextInputFormatKeyValueTextInputFormatNLineInputFormatCombineTextInputFormat自定义InputFormat等。
  TextInputFormat 是默认的 FileInputFormat 实现类。按行读取每条记录。键是存储该行在整个文件中的起始字节偏移量, LongWritable类型。值是这行的内容,不包括任何行终止符(换行符和回车符),Text类型。
  以下是一个示例,比如,一个分片包含了如下 4 条文本记录。

Rich learning form
Intelligent learning engine
Learning more convenient
From the real demand for more close to the enterprise

  每条记录表示为以下键/值对:

(0,Rich learning form)
(20,Intelligent learning engine)
(49,Learning more convenient)
(74,From the real demand for more close to the enterprise)

3.2 CombineTextInputFormat切片机制

  框架默认的 TextInputFormat 切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个 MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。

  • 应用场景:
    • CombineTextInputFormat 用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 MapTask 处理;
  • 虚拟存储切片最大值设置
    • CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);(4M)
    • 注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值;
  • 切片机制
    • 生成切片过程包括:虚拟存储过程和切片过程二部分。

在这里插入图片描述

  • 虚拟存储过程:
    • 将输入目录下所有文件大小,依次和设置的 setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)
    • 例如 setMaxInputSplitSize 值为 4M,输入文件大小为 8.02M,则先逻辑上分成一个 4M。剩余的大小为 4.02M,如果按照 4M 逻辑划分,就会出现 0.02M 的小的虚拟存储文件,所以将剩余的 4.02M 文件切分成(2.01M和2.01M)两个文件;
  • 切片过程:
    • 判断虚拟存储的文件大小是否大于 setMaxInputSplitSize 值,大于等于则单独形成一个切片;
    • 如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
    • 测试举例:
      • 有 4 个小文件大小分别为 1.7M、5.1M、3.4M 以及 6.8M 这四个小文件,则虚拟存储之后形成 6 个文件块,大小分别为:
        1.7M,(2.55M、2.55M),3.4M 以及(3.4M、3.4M)
      • 最终会形成 3 个切片,大小分别为:
        (1.7+2.55) M,(2.55+3.4) M,(3.4+3.4) M
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MapReduce程序中,计数器是一种用于跟踪作业运行时信息的机制。我们可以通过计数器来记录某个特定事件发生的次数或者某个特定状态的数量。例如,我们可以使用计数器来记录程序中处理的行数、错误的数量、跳过的记录数等等。 MapReduce框架提供了两种类型的计数器:任务计数器和作业计数器。任务计数器是每个MapReduce任务独有的计数器,而作业计数器是整个作业共享的计数器。 任务计数器可以通过TaskAttemptContext对象的getCounter()方法获取。TaskAttemptContext是MapReduce任务中的一个上下文对象,该对象包含了任务的所有信息,包括计数器。任务计数器可以用于跟踪任务内部的事件或状态。 作业计数器可以通过JobContext对象的getCounter()方法获取。JobContext是整个MapReduce作业的上下文对象,该对象包含了作业的所有信息,包括计数器。作业计数器可以用于跟踪整个作业的事件或状态。 计数器可以通过以下方式进行操作: 1. 增加计数器的值:通过调用计数器的increment()方法,可以将计数器的值增加指定的数量。 2. 获取计数器的值:通过调用计数器的getValue()方法,可以获取计数器的当前值。 3. 设置计数器的值:通过调用计数器的setValue()方法,可以设置计数器的值。 在MapReduce程序中,计数器通常用于跟踪任务或作业的进度,以及记录一些重要的事件或状态。使用计数器可以帮助我们更好地理解程序的运行情况,以便对程序进行优化和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大Null

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

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

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

打赏作者

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

抵扣说明:

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

余额充值