一、认识 MapReduce

1. 核心思想

  • 分而治之:将大数据拆分为独立数据块,分布式处理后汇总结果。
  • 抽象为 Map 和 Reduce 操作:Map 处理数据生成中间结果,Reduce 聚合中间结果输出最终值。
  • 隐藏系统细节:自动实现并行化、任务调度、容错等底层操作。

2. 编程模型

  • 定义:分布式离线并行计算框架,适用于 PB 级以上海量数据处理。
  • 特点:易于编程、扩展性好、高容错、支持离线处理。
  • 核心阶段:
    • Map 阶段:读取数据并解析为键值对(K-V 对)。
    • Reduce 阶段:对 K-V 对归并排序,计算最终结果。
  • 执行流程:数据分块→Map 任务读取处理→生成 K-V 对→Reduce 任务聚合→输出结果。

3. 经典案例 ——WordCount

  • 问题:统计 PB 级英文文件中单词出现次数。
  • 解决思路:
    • Map 阶段:拆分文件,统计单个文件中单词出现次数,输出(单词,1)。
    • Reduce 阶段:累加同一单词在不同文件中的次数,输出(单词,总次数)。
  • 编程步骤:实现 Mapper→实现 Reducer→创建 MapReduce 作业→打包运行。

二、MapReduce 作业解析

1. 作业(Job)定义

  • 指用户提交的 MapReduce 应用程序,是计算请求的载体。
  • 核心功能:提交作业、跟踪进度、访问任务报告、获取集群状态。
  • 提交流程:检查输入输出格式→计算 InputSplit→复制 jar 包和配置→提交到 ResourceManager。
  • 提交方法:Job.submit ()(立即返回)、Job.waitForCompletion (boolean)(等待完成)。

2. 资源调度

  • 核心模块:客户端(提交作业)、ResourceManager(资源调度)、NodeManager(启动任务)、ApplicationMaster(管理作业)、分布式文件系统(存储文件)。
  • 调度流程:客户端提交作业→ResourceManager 分配资源→NodeManager 启动 Container→ApplicationMaster 运行任务。

3. 运行流程

  • Map 阶段:FileInputFormat→InputSplit→RecordReader→Mapper→Partition→Sort→Combiner。
  • Reduce 阶段:Reducer→FileOutputFormat→RecordWriter。

三、MapReduce 工作原理

1. Map Task 工作原理

  • 输入数据:InputFormat 分割文件为 InputSplit,每个 split 对应一个 Map Task。
  • 中间结果处理:数据写入内存缓冲区(默认 100MB),达到 80% 阈值时溢写到磁盘。
  • 排序与合并:溢写前对 Key 排序,多个溢写文件最终合并为一个文件。

2. Reduce Task 工作原理

  • 数据拉取:Map Task 完成后,Reduce Task 拉取对应分区的中间结果。
  • 数据合并:合并拉取的数据,为 Reduce 计算做准备。
  • 结果输出:执行 Reduce 算法,将结果写入 HDFS。

四、Shuffle 阶段

1. 概念

  • 指 Mapper 之后到 Reducer 之前的过程,将无规则中间数据转换为有序数据。
  • 分为 Map 端 Shuffle 和 Reduce 端 Shuffle。

2. Map 端 Shuffle

  • Partition 分区:根据 Key 和 Reduce 数量分配数据所属的 Reduce Task。
  • 环形缓冲区:缓存中间结果,满 80% 溢写磁盘。
  • Spill 溢写排序:溢写前按分区和 Key 排序,可执行 Combiner 优化。
  • Merg 文件合并:多个溢写文件合并为一个最终文件。

3. Reduce 端 Shuffle

  • Copy 复制:通过 Http 方式拉取 Map 端对应分区数据。
  • Merge 合并:数据存入缓冲区,满阈值溢写磁盘,最终合并为 Reduce 输入数据。
  • Reduce 执行:处理合并后的数据,输出结果到 HDFS。

五、MapReduce 编程组件

1. InputFormat 组件

  • 功能:定义作业输入规范,拆分文件为 InputSplit,创建 RecordReader。
  • 常用子类:FileInputFormat(设置输入路径)、TextInputFormat(默认,按行读取)等。

2. OutputFormat 组件

  • 功能:定义作业输出规范,转换输出格式以支持跨系统互操作。
  • 输出规则:输出文件数与 Reduce 任务数一致,默认文件名为 part-r-00000。
  • 常用子类:TextOutputFormat(默认,文本格式)、SequenceFileOutputFormat(序列文件格式)等。

3. RecordReader 和 RecordWriter

  • RecordReader:从 InputSplit 读取 K-V 对,默认 LineRecordReader(偏移量为 Key,行数据为 Value)。
  • RecordWriter:将 Reduce 输出的 K-V 对写入文件系统,核心方法为 write ()(写入数据)和 close ()(关闭输出)。

4. Partitioner 组件

  • 功能:决定 Map 输出的 Key 分配给哪个 Reduce Task,数量与 Reduce 任务数一致。
  • 默认实现:HashPartitioner(按 Key 的 Hash 值取模分配)。
  • 自定义分区:可解决数据倾斜问题,按业务规则分配数据。

5. Combiner 组件

  • 功能:Map 阶段的 Mini Reduce,合并相同 Key 的中间结果,减少网络传输量。
  • 适用场景:累加求和、取最大值等(不影响最终结果的操作),不适用于求平均值。

六、优化 —— 数据倾斜

1. 问题定义

  • 大量数据集中分配到单个分区,导致部分节点忙碌、其他节点空闲,降低处理效率。

2. 解决方法

  • 自定义分区:按业务规则均匀分配数据。
  • 重新设计 Key:给 Key 添加随机数,避免集中分配。
  • 使用 Combiner:提前合并相同 Key 数据,减少传输量。
  • 增加 Reduce 任务数:分散数据处理压力。
  • 增加 Jvm 内存:提升单个节点数据处理能力。

七、经典案例

1. 排序

  • 部分排序:默认排序方式,每个 Reduce 输出按 Key 排序,全局无序。
  • 全排序:所有 Reduce 输出全局有序,实现方式包括单 Reduce 任务、自定义分区、Key 采样。

2. 倒序索引

  • 功能:统计单词在各文件中的出现次数,支持按单词查询文件位置。
  • 实现步骤:准备多文件数据→编写 Mapper(输出(单词 - 文件名,1))→Reducer(聚合次数)→运行作业。

3. Join

  • 功能:关联多个数据源的数据(如姓名与城市编号关联)。
  • 实现步骤:准备关联数据→编写 Mapper(输出(关联键,数据类型 - 数据))→Reducer(按关联键合并数据)→输出结果。

4. 平均分以及百分比

  • 功能:计算学生平均分,统计各分数段人数占比。
  • 实现思路:Map 阶段计算平均分并标记分数段→Reduce 阶段统计各分数段人数→计算百分比。

5. 过滤敏感词汇

  • 功能:从文档中过滤指定敏感词。
  • 实现步骤:准备文档和敏感词库→编写 Mapper(匹配敏感词并过滤)→Reducer(输出过滤后内容)→运行作业。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐