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. MFC学习 标签页与属性页及各常用控件使用

    参考 http://blog.csdn.net/anye3000/article/details/6700023 CTabCtrl: BOOL CTabTestDlg::OnInitDialog() ...

  2. app控件获取之uiautomatorviewer

    初探 在Android的SDk提供了以下的工具来支持我们进行UI自动化测试: uiautomatorviewer:用来扫描和分析Android应用程序的UI控件的工具. uiautomator:一个包 ...

  3. UDKtoUE4Tool-UDKUE3资源移植UE4工具

    UDKtoUE4Tool UDKtoUE4Tool 是一个把UE3/UDK资源包(T3D格式)转换成UE4(T3D格式)的工具.作者Matt3D使用C#实现,未来考虑发布到Unreal Marketp ...

  4. SICP 1.1-1.5

    1.1 a = b = nil 1.2 (/ (+ (- (- (+ (/ ))))) (* (- ) (- )) 1.3 a = b = nil 1.4... 1.5 (define (p) (p) ...

  5. Oracle建立表空间和用户

    Oracle建立表空间和用户 建立表空间和用户的步骤: 用户 建立:create user 用户名 identified by "密码"; 授权:grant create sess ...

  6. 图形化Cisco设备管理实践(附安装配置视频)

    图形化Cisco设备管理实践 Ciscoworks 2000是Cisco公司推出的基于SNMP协议的网络管理系统,通过它网络管理人员可以方便快捷地完成设备的配置.管理.监控和故障分析等任务, Cisc ...

  7. 2016-03-24:Windows内存泄露分析工具

    参考资料 100%正确的内存泄漏分析工具 ------ tMemMonitor (TMM)

  8. js中object的申明方法

    //js中的对象申明使用new Object(); //object类型的数据类似于数组通过下表来访问其中的值 //example1 var person=new Object(); person.n ...

  9. 转载:SMS软件FESWMS模型使用体会

    自学了SMS-FESWMS几个月,从其原理到具体应用都已经比较熟悉.感觉这个软件还是有许多不足,这也是需要进一步提高和改进的地方.下面谈谈自己的一些感受和体会. 首先,对一些比较简单的模型,软件的计算 ...

  10. ASP.NET的SEO:HTTP报头状态码---内容重定向

    本系列目录 我们经常说"404错误",你知道他指的是什么意思么? 404其实是Http报头所包含的一个"状态码",表明该Http请求失败.那么除此之外,还有哪些 ...