partition的作用是把环形缓冲区中的map输出分区存储,以便分配给不同的reducer。

把内部的实现写下来,作为一个学习笔记

  1. 在map函数,调用context.write()时,会去调用分区函数,得到分区号,把分区号一块写进keyvalue的元数据。
  2. 当环形缓冲区达到溢写磁盘时
    • a) 对每个分区内的数据进行排序
    • b) 把每个分区内的数据写到磁盘

下面通过代码来说明

1

context.write(K,V) -> MapTask.NewOutputCollector.write(K, V) -> MapOutputBuffer.collect(K, V, partion)

void MapTask.NewOutputCollector.write(K key, V value) {
collector.collect(key, value,
partitioner.getPartition(key, value, partitions)); // 调用分区函数
} MapOutputBuffer.collect(K, V, partion) {
...
kvmeta.put(kvindex + PARTITION, partition); // 把分区号一块写进keyvalue元数据
...
}

2-a)

MapTask.MapOutputBuffer.flush()->MapTask.MapOutputBuffer.sortAndSpill()->IndexedSortable.compare(final int mi, final int mj)


void MapTask.MapOutputBuffer.sortAndSpill() {
...
sorter.sort(MapOutputBuffer.this, mstart, mend, reporter); // 对数据进行排序,默认采用快速排序。调用了下面的compare()方法
...
} // 比较 mi和mj所对应的两个key,这个方法先比较分区号,如果分区号相同,才有必要比较key,实现了按各个分区内的key进行排序
public int MapTask.MapOutputBuffer.compare(final int mi, final int mj) {
final int kvi = offsetFor(mi % maxRec);
final int kvj = offsetFor(mj % maxRec);
final int kvip = kvmeta.get(kvi + PARTITION); // 从keyvalue元数据取出mi的分区号
final int kvjp = kvmeta.get(kvj + PARTITION); // 从keyvalue元数据取出mj的分区号
// sort by partition
if (kvip != kvjp) { // 如果分区号不相同,直接比较分区号:分区号的大小决定了写磁盘时的先后顺序
return kvip - kvjp;
}
// sort by key // 分区号相同,再比较key,这个方法调用RawComparator.compare(buffer, s1, l1, s2, l2);
return comparator.compare(kvbuffer,
kvmeta.get(kvi + KEYSTART), // key1的开始位置
kvmeta.get(kvi + VALSTART) - kvmeta.get(kvi + KEYSTART), // key1的结束位置
kvbuffer,
kvmeta.get(kvj + KEYSTART), //key2的开始位置
kvmeta.get(kvj + VALSTART) - kvmeta.get(kvj + KEYSTART)); // key2的开始位置
}
2-b)

a和b都是在sortAndSpill()中


void MapTask.MapOutputBuffer.sortAndSpill() {
...
sorter.sort(MapOutputBuffer.this, mstart, mend, reporter); // 对数据进行排序,默认采用快速排序。调用了下面的compare()方法
... // 按分区号从小到大,一个分区一个分区写进磁盘
for (int i = 0; i < partitions; ++i) {
...
while (spindex < mend &&
kvmeta.get(offsetFor(spindex % maxRec) + PARTITION) == i) { // 从元数据读出kv分区号,如果是当前正在写磁盘的分区号,就把这个kv写到磁盘
final int kvoff = offsetFor(spindex % maxRec);
int keystart = kvmeta.get(kvoff + KEYSTART);
int valstart = kvmeta.get(kvoff + VALSTART);
key.reset(kvbuffer, keystart, valstart - keystart);
getVBytesForOffset(kvoff, value);
writer.append(key, value); // 把kv写到磁盘
++spindex;
}
} ...
}

经过上面这些步骤,环形缓冲区内的kv,就按分区写到磁盘,并且每个分区内的数据是有序的。

当然,这并不能保证同一个分区内,先后溢写的数据是有序的。后面使用归并排序对磁盘上的分区数据再做一轮排序,这个以后再做分析。

partition实现的更多相关文章

  1. Partition:增加分区

    在关系型 DB中,分区表经常使用DateKey(int 数据类型)作为Partition Column,每个月的数据填充到同一个Partition中,由于在Fore-End呈现的报表大多数是基于Mon ...

  2. Partition:Partiton Scheme是否指定Next Used?

    在SQL Server中,为Partition Scheme多次指定Next Used,不会出错,最后一次指定的FileGroup是Partition Scheme的Next Used,建议,在执行P ...

  3. Partition:分区切换(Switch)

    在SQL Server中,对超级大表做数据归档,使用select和delete命令是十分耗费CPU时间和Disk空间的,SQL Server必须记录相应数量的事务日志,而使用switch操作归档分区表 ...

  4. sql 分组取最新的数据sqlserver巧用row_number和partition by分组取top数据

    SQL Server 2005后之后,引入了row_number()函数,row_number()函数的分组排序功能使这种操作变得非常简单 分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系 ...

  5. Oracle Partition Outer Join 稠化报表

    partition outer join实现将稀疏数据转为稠密数据,举例: with t as (select deptno, job, sum(sal) sum_sal from emp group ...

  6. SQLServer中Partition By 函数的使用

    今天群里看到一个问题,在这里概述下:查询出不同分类下的最新记录.一看这不是很简单的么,要分类那就用Group By;要最新记录就用Order By呗.然后在自己的表中试着做出来: 首先呢我把表中的数据 ...

  7. [LeetCode] Partition Equal Subset Sum 相同子集和分割

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  8. [LeetCode] Partition List 划分链表

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  9. 快速排序中的partition函数的枢纽元选择,代码细节,以及其标准实现

    很多笔试面试都喜欢考察快排,叫你手写一个也不是啥事.我很早之前就学了这个,对快速排序的过程是很清楚的.但是最近自己尝试手写,发现之前对算法的细节把握不够精准,很多地方甚至只是大脑中的一个映像,而没有理 ...

  10. [bigdata] kafka基本命令 -- 迁移topic partition到指定的broker

    版本 0.9.2 创建topic bin/kafka-topics.sh --create --topic topic_name --partition 6 --replication-factor ...

随机推荐

  1. Grub2 使用摘记

    >>>不使用子菜单 # sudo vim /etc/default/grub添加配置:GRUB_DISABLE_SUBMENU=yFrom:http://tieba.baidu.co ...

  2. windows下忘记mysql密码怎么办

    长时间不用mysql,密码忘记了怎么办,按照下面的步骤可以重新设置密码: 1.先把mysql服务停了,右键计算机-->选择管理-->选择服务和应用程序-->选择服务-->找到m ...

  3. 解决setInterval计时器不准的问题

    在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在s ...

  4. int型的数到底最大值是多少?

    本文摘自:http://blog.csdn.net/friendbaby/article/details/6822690 刚才在百度知道上看见一个网友问int型的数最大能存多少.这个问题其实计算机系统 ...

  5. 关于 mysql 2003 客户端连接报错的处理方法

    在连接到 mysql 数据库服务器时,有时会在客户端报出 2003 的错误代码,并提示: 无法连接到服务器,但服务器却可以 ping 通,可能的原因如下: 1.网络不通.检查能不能ping通. 2.防 ...

  6. 在yii中使用gearman

    最近项目需要将利用gearman进行任务调度,目前所用框架为yii,在部署好gearman后,试图在yii中调用gearman,一直报错: 提示reverse函数没有定义,明明已经定义了啊!可能是当时 ...

  7. 如何由jdk的安装版本改成非安装版本

    背景. 官网一般只提供windows下的exe文件,不提供zip打包文件.有些不愿意使用安装版本. 解决方法 本文以windows 7下安装jdk-6u35-windows-x64.exe为例说明 1 ...

  8. 洛谷P2320 鬼谷子的钱袋

    P2320 06湖南 鬼谷子的钱袋 171通过 480提交 题目提供者xmyzwls 标签各省省选 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 题目有误 数据需要特判 评测系统太神了 题目 ...

  9. TCP/IP详解学习笔记(4)-- ARP 和 RARP

    1.ARP      地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP地址时确地址解析协议定其物理地址的一种协议.      在TCP/IP协议中,A ...

  10. UITableView 详解 ()

    (原本取至D了个L微信公众号) UITableView 详解 一.建立 UITableView DataTable = [[UITableView alloc] initWithFrame:CGRec ...