MapReduce的执行过程(以及其中排序)

2023-12-13 14:31:26

Map阶段(MapTask): 切片(Split)-----读取数据(Read)-------交给Mapper处理(Map)------分区和排序(sort)
Reduce阶段(ReduceTask): 拷贝数据(copy)------排序(sort)-----合并(reduce)-----写出(write)

1、Map task读取:
框架调用InputFormat类的子类读取HDFS中文件数据,把文件转换为InputSplit。
默认,文件的一个block对应一个InputSplit,一个InputSplit对应一个map task。
一个InputSplit中的数据会被RecordReader解析成<k1,v1>。
默认,InputSplit中的一行解析成一个<k1,v1>。
默认,v1表示一行的内容,k1表示偏移量。
map:
框架调用mapper 类中的map方法,接收<k1,v1>输出<k2,v2>,有多少个<k1,v1>,就执行多少次map分区: 框架对mapp的输出进行分区,分区的目的是确定哪些<k2,v2>进入哪个reduce task。默认只有一个分区。
排序分组:框架对不同分区中的<k2,v2>进行排序分组.排序是按照k2进行排序。分组指的是相同k2的v2分到一个组中。分组不会减少<k2,v2>的数量。(快速排序)
combiner:可以在map task中对<k2,{v2}>执行reduce归约。
写入本地:框架对map的输出写入到Linux本地磁盘
2、reduce taskshuffle:
框架根据map不同分区中的数据,通过网络copy到不同的reduce节点合并
排序分组:每个reduce会把多个map传来的<k2,{v2}>进行合并排序分组(归并排序)
reduce:框架调用reduce<k2,v2s>,有多少个分组就回执行多少回reduce
写入HDFS:
框架对reduce输出的数据写入到hdfs中

快速排序:
个人理解:
就是归位,分区,递归
比如: 4,6,9,2,1,3,8 这个数组,要对它使用快速排序
首先,选第一个 4 对它进行归位 ,依次和4进行比较得到
左边: 2,1,3
右边:6,9,8
这样我们就的得到了 2,1,3,4,6,9,8
然后在对两边进行递归的操作。

python 实现

def partition(li, left, right):
    tmp = li[left]
    # 当两边搜索并没有重合的时候就进行双向查找
    while left < right:
        # 这一级两个判断条件
        # 因为li[right] >= tmp退出说明在right出找到了小于tmp的值,这样填到left就行了
        # 因为left < right退出是因为left右侧的所有值都大于tmp,left已经和right重合了
        while left < right and li[right] >= tmp:  # left有空缺,需要right小于tmp的值来填补
            right = right - 1  # 往前一位接着找
        li[left] = li[right]  # 将右边的数写到左边空缺处
        # 找到之后,right出现空缺,应从left找比tmp大的数填到right
        while left < right and li[left] <= tmp:
            left = left + 1
        li[right] = li[left]

    # 当双向查找两边重合时侯,left=right,将值写入
    li[left] = tmp
    return li

li = [5, 7, 4, 6, 3, 1, 2, 9, 8]
result = partition(li, 0, len(li)-1)
print(result)

def quick_sort(li, left, right):
    if left < right:  # 至少两个元素
        mid = partition(li, left, right)
        # 拿到mid之后就能对两边的部分进行相同的整理
        quick_sort(li, left, mid-1)
        quick_sort(li, mid+1, right)

li = [5,7,4,6,3,1,2,9,8]
quick_sort(li, 0, len(li)-1)

归并排序:
是将数组按 left mid right 划分成两个部分,要求每个部分是有序的,然后假设有两个指针指在,两个部分的第一个位置,开始比较,较小的被放到一个临时集合中,指针移动到下一个位置,然后继续比较,直到一方没有下一个值 ,另一方剩下的就是最大的一部分直接放在临时集合最后,整个排序完成。
python 实现

# 实现一次归并的过程
# 前提是已经拿到两个有序子的列表
def merge(li, low, mid, high):
    """
    :param li:列表
    :param low:第一段有序子列表起始位
    :param mid:第一段有序子列表终止位
    :param high:第二段有序子列表终止位
    :return:一次归并操作之后的整个列表
    """
    # i,j开始分别指向两个有序子序列的起始位
    i = low
    j = mid + 1
    ltmp = []  # 存储结果用
    while i<=mid and j<=high:  # 只要两个有序子序列都有数
        if li[i] < li[j]:
           ltmp.append(li[i])
           i = i + 1
        else:
            ltmp.append(li[j])
            j = j + 1
    # 两部分中有一部分拿光了
    while i <= mid:  # 说明后面的拿光了
        ltmp.append(li[i])
        i = i + 1
    while j <= high:  # 说明前面的拿光了
        ltmp.append(li[j])
        j = j + 1
    li[low:high+1] = ltmp  # 将结果写回去

li = [0,2,4,6,8,1,3,5,7,9]
merge(li, 0, 4, len(li)-1)

文章来源:https://blog.csdn.net/Logan_addoil/article/details/134878869
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。