使用RawComparator加速Hadoop程序

在前面两篇文章[1][2]中我们介绍了Hadoop序列化的相关知识,包括Writable接口与Writable对象以及如何编写定制的Writable类,深入的分析了Writable类序列化之后占用的字节空间以及字节序列的构成。我们指出Hadoop序列化是Hadoop的核心部分之一,了解和分析Writable类的相关知识有助于我们理解Hadoop序列化的工作方式以及选择合适的Writable类作为MapReduce的键和值,以达到高效利用磁盘空间以及快速读写对象。因为在数据密集型计算中,在网络数据的传输是影响计算效率的一个重要因素,选择合适的Writable对象不但减小了磁盘空间,而且更重要的是其减小了需要在网络中传输的数据量,从而加快了程序的速度。

在本文中我们介绍另外一种方法加快程序的速度,这就是使用RawComparator加速Hadoop程序。我们知道作为键(Key)的Writable类必须实现WritableComparable接口,以实现对键进行排序的功能。Writable类进行比较时,Hadoop的默认方式是先将序列化后的对象字节流反序列化为对象,然后再进行比较(compareTo方法),比较过程需要一个反序列化的步骤。RawComparator的做法是不进行反序列化,而是在字节流层面进行比较,这样就省下了反序列化过程,从而加速程序的运行。Hadoop自身提供的IntWritable、LongWritabe等类已经实现了这种优化,使这些Writable类作为键进行比较时,直接使用序列化的字节数组进行比较大小,而不用进行反序列化。

RawComparator的实现

在Hadoop中编写Writable的RawComparator一般不直接继承RawComparator类,而是继承RawComparator的子类WritableComparator,因为WritableComparator类为我们提供了一些有用的工具方法,比如从字节数组中读取int、long和vlong等值。下面是上两篇文章中我们定制的MyWritable类的RawComparator实现,定制的MyWritable由两个VLongWritable对组成,为了添加RawComparator功能,Writable类必须实现WritableComparable接口,这里不再展示实现了WritableComparable接口的MyWritableComparable类的全部内容,而只是MyWritableComparable类中Comparator的实现,完整的代码可以在github中找到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...//omitted for conciseness
/**
* A RawComparator that compares serialized VlongWritable Pair
* compare method decode long value from serialized byte array one by one
*
* @author yoyzhou
*
* */
public static class Comparator extends WritableComparator { public Comparator() {
super(MyWritableComparable.class);
} public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { int cmp = 1;
//determine how many bytes the first VLong takes
int n1 = WritableUtils.decodeVIntSize(b1[s1]);
int n2 = WritableUtils.decodeVIntSize(b2[s2]); try {
//read value from VLongWritable byte array
long l11 = readVLong(b1, s1);
long l21 = readVLong(b2, s2); cmp = l11 > l21 ? 1 : (l11 == l21 ? 0 : -1);
if (cmp != 0) { return cmp; } else { long l12 = readVLong(b1, s1 + n1);
long l22 = readVLong(b2, s2 + n2);
return cmp = l12 > l22 ? 1 : (l12 == l22 ? 0 : -1);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} static { // register this comparator
WritableComparator.define(MyWritableComparable.class, new Comparator());
} ...

通过上面的代码我们可以看到要实现Writable的RawComparator我们只需要重载WritableComparator的public intcompare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2)方法。在我们的例子中,通过从VLongWritable对序列化后字节数组中一个一个的读取VLongWritable的值,再进行比较。

当然编写完compare方法之后,不要忘了为Writable类注册编写的RawComparator类。

总结

为Writable类编写RawComparator必须对Writable本身序列化之后的字节数组有清晰的了解,知道如何从字节数组中读取Writable对象的值,而这正是我们前两篇关于Hadoop序列化和Writable接口的文章所要阐述的内容。

通过以上的三篇文章,我们了解了Hadoop Writable接口,如何编写自己的Writable类,Writable类的字节序列长度与其构成,以及如何为Writable类编写RawComparator来为Hadoop提速。

参考资料

Tom White, Hadoop: The Definitive Guide, 3rd Edition

Hadoop序列化与Writable接口(一)

Hadoop序列化与Writable接口(二)

--EOF--

使用RawComparator加速Hadoop程序的更多相关文章

  1. IntelliJ IDEA + Maven环境编写第一个hadoop程序

    1. 新建IntelliJ下的maven项目 点击File->New->Project,在弹出的对话框中选择Maven,JDK选择你自己安装的版本,点击Next 2. 填写Maven的Gr ...

  2. [转载]高效使用matlab之四:一个加速matlab程序的例子

    原文地址:http://www.bfcat.com/index.php/2012/11/speed-up-app/ 这篇文章原文是matlab网站上的,我把它翻译过来同时自己也学习一下.原文见这里 这 ...

  3. 深入剖析HADOOP程序日志

    深入剖析HADOOP程序日志 前提 本文来自于 博客园 逖靖寒的世界 http://gpcuster.cnblogs.com 了解log4j的使用. 正文 本文来自于 博客园 逖靖寒的世界 http: ...

  4. eclipse运行hadoop程序报错:Connection refused: no further information

    eclipse运行hadoop程序报错:Connection refused: no further information log4j:WARN No appenders could be foun ...

  5. WIN7下运行hadoop程序报:Failed to locate the winutils binary in the hadoop binary path

    之前在mac上调试hadoop程序(mac之前配置过hadoop环境)一直都是正常的.因为工作需要,需要在windows上先调试该程序,然后再转到linux下.程序运行的过程中,报Failed to ...

  6. 运行第一个Hadoop程序,WordCount

    系统: Ubuntu14.04 Hadoop版本: 2.7.2 参照http://www.cnblogs.com/taichu/p/5264185.html中的分享,来学习运行第一个hadoop程序. ...

  7. 使用ToolRunner运行Hadoop程序基本原理分析

    为了简化命令行方式运行作业,Hadoop自带了一些辅助类.GenericOptionsParser是一个类,用来解释常用的Hadoop命令行选项,并根据需要,为Configuration对象设置相应的 ...

  8. 第一个Hadoop程序——Hello Hadoop

    本人原创,转载请注明出处:http://blog.csdn.net/panjunbiao/article/details/12773163 下载Hadoop程序包,下载地址:http://hadoop ...

  9. 用Cython加速Python程序以及包装C程序简单测试

    用Cython加速Python程序 我没有拼错,就是Cython,C+Python=Cython! 我们来看看Cython的威力,先运行下边的程序: import time def fib(n): i ...

随机推荐

  1. opencv颜色提取color filting

    # -*- coding: utf-8 -* import numpy as np import cv2 cap = cv2.VideoCapture(0) while True: _ , frame ...

  2. JAVA经典总结

    Java经典实例(第二版) 1. 获取环境变量 Java代码 1. System.getenv("PATH"); 2. System.getenv("JAVA_HOME& ...

  3. 内网 LAN IPv6 环境配置 H3C S5500 Huawei S5700

    # 使能IPv6报文转发功能. <Sysname> system-view [Sysname] ipv6 # 使能DHCPv6服务器功能. <Sysname> system-v ...

  4. css布局(转载)

    单列布局 水平居中 水平居中的页面布局中最为常见的一种布局形式,多出现于标题,以及内容区域的组织形式,下面介绍四种实现水平居中的方法(注:下面各个实例中实现的是child元素的对齐操作,child元素 ...

  5. field字段错位手动更改方法

    update tbprotocolex set field='1' where name='ICMP';update tbprotocolex set field='1' where name='DN ...

  6. Prism 4 文档 ---第2章:初始化Prism应用程序

     这一章节介绍Prism应用程序启动和运行时发生的内容.Prism应用程序在启动时需要有注册和配置的过程,这就是所谓的自自启动程序. 什么是自启动引导程序?     引导程序是一个类,它负责使用Pri ...

  7. node 封装db层

    var db = {}; var mysql = require('mysql'); var pool = mysql.createPool({ connectionLimit: , host: '1 ...

  8. sql 日志统计-日、周、月活跃数

    近日网站需求:统计日志表的 日.周.月活跃数.最终研究了出来了,分享给大家看下.  如果有更好的sql语句也可以评论下方. --日活跃量 ), cr.AddTime, )as addtimt,COUN ...

  9. Quartz创建多个不同名字的scheduler实例

    _http://my.oschina.net/laiweiwei/blog/122280 需求创建多个不同的Scheduler实例,每个实例自主启动.关闭 问题 如果直接用 SchedulerFact ...

  10. openoffice在连接时有错误,无法连接上

    openoffice在连接时有错误,无法连接上 报如下错误: java.net.ConnectException: connection failed: socket,host=localhost,p ...