大数据学习之MapReduce
MapReduce是一个分布式运算程序的编程框架,其核心功能是将用户编写的业务逻辑代码和自身的组件整合成
一个完整的分布式运算程序 并发运行在一个hadoop集群上
优点:
1、易于编程 实现一些简单的接口就可以实现一个分布式车程序
2、良好的扩展性 可以通过简单的扩充机器来扩展计算能力
3、高容错性 其中一台及其挂了,他可以把上边的运算任务转移到另外一个节点上运行 不至于导致任务失败
而这个过程不需要人工介入
4、适合海量数据的离线处理
缺点:
1、不擅长实时运算
2、不擅长流式运算 输出的结果集是静态的
3、每个MapReduce作业的输出结果都会写入磁盘造成大量的磁盘IO 导致性能较低
(技术选型的时候用到)
MapReduce编程思想
MapReduce分为两个阶段 map阶段 和reduce阶段
map阶段的并发MapTask 完全并行运行 互不相干
reduce阶段并发ReduceTask 完全互不相干 但是他们的数据依赖于上一个阶段的maptask并发实例的输出
MapReduce编程模型只包含一个map阶段和一个reduce阶段 如果用户的业务逻辑十分复杂那么就只能多几个
MapReduce程序并行运行
MapReduce计算流程
MapTask阶段(map逻辑作用在文件数据的每一行上)
1、分片格式化数据源
1)将源文件划分为大小相等的小的数据块 默认128M(在逻辑上切块 实际上并没有切) 也就是split分片 然后hadoop会为每一个split分片
构建一个map任务 并由该任务运行自定义的map函数 从而处理分片中的每一个记录
2)格式化操作 将划分好的分片格式化为<key value>形式的数据 key代表偏移量 value代表每一行的内容
注意:1、切片的大小可以自己控制 设置的时候根据block快的个数和计算资源的个数进行调整 并且split
切片的大小是128M的整数倍
2、每一个split会产生一个map任务 切分完成后 会拿倒数第一和倒数第二个切片中的数据实际大小
与128*1.1比较 如果小于这个阀值 那么这两个切片会合在一起生成一个map任务
3、MapReduce不适合处理小的数据
当数据不足128M时也会以一个block快的形式存储 当产生map任务时 一个block块产生一个
split切片 每个split切片产生一个map任务 导致map任务越开越多 处理速度反而减慢
2、执行map任务
hadoop为每个map任务提供了一个内存环形缓冲区(默认100M)split分片经过map任务处理后的中间结果会写入内存
缓冲区 当写入的数据达到80M的阀值之后 hadoop会启动一个线程将缓冲区的数据写入磁盘中,同时不影响map处理的
结果继续写入缓冲区
注意:
环形缓冲区做快速排序 对前面分区之后的数据进行排序 使得相同编号在一起
给每条数据取hash值与reduce得个数取余得到一个序号 确定这条数据将来到那个reduce里边去处理
环形缓冲区中每80%的数据给完序号后也会重新排序(快排)
在写入缓冲区时候 MapReduce会对key进行排序,如果中间结果比较大会形成多个溢写文件,最后就算缓冲区的数据
不足128M 也会全部写入磁盘 最后将多个溢写文件合并成一个文件
3、shuffle阶段
MapReduce过程中map阶段的处理数据通过shuffle分发给reduce阶段 在分发的过程中 对数据进行分区和排序
Reduce阶段
1、将map阶段输出的数据作为reduce阶段的输入数据 用户可以自定义reduce方法进行逻辑处理 最终以<key value>的形式
输出
2、每一个reduce会去map任务中拉去对应的数据 会拉到很多分数据 所以在执行reduce之前会对拉取过来的小文件进行合并
(归并排序) 将序号去掉(文件与文件之间是无序的 文件内不是有序的)
MapReduce编程规范
Mapper阶段
1、用户自定义的Mapper要继承自己的父类
2、Mapper的输入形式是KV对的形式
3、Mapper中的业务逻辑写在map方法中
4、Mapper的输出格式是KV格式
5、map()方法对每一个<K,V>调用一次
Reduce阶段
1、用户自定义的reduce要继承自己的父类
2、reduce的输入数据类型对应Mapper的输出数据类型
3、reduce业务逻辑写在reduce()方法中
4、ReduceTask进程对每一组相同的k<K,V>组调用一次reduce方法
Driver阶段
相对与YARN集群的客户端 用于提交我们整个程序到YARN集群 提交的是封装了MapReduce程序相关的运行参数的job对象
排序
排序数MapReduce框架最重要的操作之一
maptask和reducetask均会对数据按照key进行排序,该操作属于hadoop的默认行为,任何应用程序上的数据都会被排序,而不管逻辑上是否需要
默认是按照字典排序 且默认是快速排序
概述:
对于MapReduce他会将书里的数据在释放到环形缓冲区中,当环形缓冲区的大小达到阀值(80M)时在对缓冲区中的数据进行一次快速排序,并将这些
有序的数据溢写到磁盘上,而当数据吃力完毕之后,他会对磁盘上的所有文件进行归并排序
对于ReduceTask,它从每个Maptask上远程拷贝相应的数据文件,如果文件大小超过一定的阀值,则溢写磁盘上否则存储在内存中。
如果磁盘的文件文件的数量超过一定的阀值则进行一次归并排序生成一个更大的文件,如果内存中文件大小或者数目超过一定的阀值
则进行一次合并后将数据溢写到磁盘,当所有数据完成拷贝后,ReduceTask统一对磁盘上的数据进行一次归并排序
自定义排序
1、全排序
通过实现WritableComparable接口重写compareTo方法
2、区内排序
通过重写分区函数将maptask阶段输出的数据进行分区,区内同样是按照指定顺序排序
排序方法同样实在bean中实现的
继承Partitioner<maptast阶段输出的数据类型>
重写getPartition()方法完成分区
在驱动类中关联分区job.setPartitionClass(分区类.Class)
设置reducetask的数量job.setNumReduceTasks(number)
计数器
context.getCounter(counterGroup,count).increment(1);
TextInputFormat
是默认的FileInputFormat实现类,按行读取每条记录 键是存储该行在整个文件中的起始偏移量
LongWritable类型 值是这行的值 不包括任何终止符Text类型
InputFormat
切片与MapTask并行度决定机制
1、maptask的并行度决定map阶段的任务处理并发度,进而影响整个job的处理速度
2、maptask并行度决定机制
1)数据块:block是hdfs物理上把数据分成一块一块的(实实在在存在再磁盘上)
2)数据切片:只是在逻辑上对输入进行分片,并不会在磁盘上切分成片进行存储
一个job的map阶段并行度有客户端在提交job任务时的切片数决定
每一个split切片分配一个maptask并行实例处理
默认情况下切片的大小=block块的大小
切片时不考虑数据集整体,而是针对每一个文件单独切片
源码中计算切片大小
Math.max(minSize,Math.min(maxSize,blockSize));
minSize默认大小是1
maxSize默认大小是Long>MAXValue
默认情况下切片的大小是blocksize
切片大小的设置
maxsize(切片最大值):参数如果调的比blockSize小,则会让切片变大
minsize(切片最小值):参数调的比blocksize大 可以让切片变得比blocksize大
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?