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. Redo与undo在开发中的使用

    redo:记录用户的操作.(commit) undo:相反的用操作.(rollback) checkpoint:redo真正写入物理存储.(定时写---定时策略) ================== ...

  2. [VB.NET]拖动操作的技术基础

    1.设置需要接受拖动事件的控件的AllowDrop属性为True,在开发界面时配置,不可通过代码配置 2.在DragEnter事件处理程序里,为e.Effet设置枚举值,否则拖动无效 Private ...

  3. Redis集群创建报错

    Redis集群环境:och163/och164/och165 在执行如下脚本时报错: ./src/redis-trib.rb create 10.1.253.163: 10.1.253.164: 10 ...

  4. POJ3264RMQ

    http://poj.org/problem?id=3264 #include<stdio.h> #include<string.h> #include<algorith ...

  5. VC++2005下的ADO SQL语句(like,count,distinct)和操作(转)

    http://blog.sina.com.cn/s/blog_56fd66a70100hxjf.html http://timke.blog.163.com/blog/#m=0 环境:MFC  Dia ...

  6. typedef 与define 的区别

    typedef和#define的用法与区别   typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译 ...

  7. jquery selector 使用方法

    <select class="selector"></select> 1 设置value为pxx的项选中 $(".selector"). ...

  8. Edit 方法

    1. 在FORM 的grid里面作为记录选择字段 AX 的edit 方法可以很方便地给用户提供记录选择功能,而不用在TABLE上添加新字段. 通常结合map使用,一般edit 方法格式: edit N ...

  9. mysql 常用sql操作语句

    获取数据库里所有表 SELECT TABLE_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='数据库名' 获取表里 ...

  10. iOS取证将如漫漫长夜

    日前因恐攻一案,FBI对一支已上锁的iPhone 5c束手无策,美国法院出具命令要求苹果配合,但被苹果公司执行长库克以维护安全及隐私为由悍然拒绝. 平心而论,各有其立场,但在一个犯罪案件之中,真的可以 ...