Hadoop序列化与Writable接口(二)
Hadoop序列化与Writable接口(二)
上一篇文章Hadoop序列化与Writable接口(一)介绍了Hadoop序列化,Hadoop Writable接口以及如何定制自己的Writable类,在本文中我们继续Hadoop Writable类的介绍,这一次我们关注的是Writable实例序列化之后占用的字节长度,以及Writable实例序列化之后的字节序列的构成。
为什么要考虑Writable类的字节长度
大数据程序还需要考虑序列化对象占用磁盘空间的大小吗?也许你会认为大数据不是就是数据量很大吗,那磁盘空间一定是足够足够的大,一个序列化对象仅仅占用几个到几十个字节的空间,相对磁盘空间来说,当然是不需要考虑太多;如果你的磁盘空间不够大,还是不要玩大数据的好。
上面的观点没有什么问题,大数据应用自然需要足够的磁盘空间,但是能够尽量的考虑到不同Writable类占用磁盘空间的大小,高效的利用磁盘空间也未必就是没有必要的,选择适当的Writable类的另一个作用是通过减少Writable实例的字节数,可加快数据的读取和减少网络的数据传输。
Writable类占用的字节长度
下面的表格显示的是Hadoop对Java基本类型包装后相应的Writable类占用的字节长度:
Java基本类型 | Writable实现 | 序列化后字节数 (bytes) |
boolean | BooleanWritable | 1 |
byte | ByteWritable | 1 |
short | ShortWritable | 2 |
int | IntWritable | 4 |
VIntWritable | 1–5 | |
float | FloatWritable | 4 |
long | LongWritable | 8 |
VLongWritable | 1–9 | |
double | DoubleWritable | 8 |
不同的Writable类序列化后占用的字数长度是不一样的,需要综合考虑应用中数据特征选择合适的类型。对于整数类型有两种Writable类型可以选择,一种是定长(fixed-length)Writable类型,IntWritable和LongWritable;另一种是变长(variable-length)Writable类型,VIntWritable和VLongWritable。定长类型顾名思义使用固定长度的字节数表示,比如一个IntWritable类型使用4个长度的字节表示一个int;变长类型则根据数值的大小使用相应的字节长度表示,当数值在-112~127之间时使用1个字节表示,在-112~127范围之外的数值使用头一个字节表示该数值的正负符号以及字节长度(zero-compressed encoded integer)。
定长的Writable类型适合数值均匀分布的情形,而变长的Writable类型适合数值分布不均匀的情形,一般情况下变长的Writable类型更节省空间,因为大多数情况下数值是不均匀的,对于整数类型的Writable选择,我建议:
1. 除非对数据的均匀分布很有把握,否则使用变长Writable类型
2. 除非数据的取值区间确定在int范围之内,否则为了程序的可扩展性,请选择VLongWritable类型
整型Writable的字节序列
下面将以实例的方式演示Hadoop整型Writable对象占用的字节长度以及Writable对象序列化之后字节序列的结构,特别是变长整型Writable实例,请看下面的代码和程序输出:
1 |
|
程序输出:
Byte array per IntWritable(1,000,000,000) is: \
3b9aca00 with length: 4
Byte array per LongWritable(1,000,000,000) is: \
000000003b9aca00 with length: 8
Byte array per VIntWritable(1,000,000,000) is: \
8c3b9aca00 with length: 5
Byte array per VLongWritable(1,000,000,000) is:\
8c3b9aca00 with length: 5
从上面的输出我们可以看出:
+ 对1,000,000,000的表示不同的Writable占用了不同字节长度
+ 变长Writable类型并不总是比定长类型更加节省空间,当IntWritable占用4个字节、LongWritable占用8个字节时,相应的变长Writable需要一个额外的字节来存放正负信息和字节长度。所以回到前面的整数类型选择的问题上,选择出最合适的整数Writable类型,我们应该对数值的总体分布有一定的认识。
Text的字节序列
可以简单的认为Text类是java.lang.String的Writable类型,但是要注意的是Text类对于Unicode字符采用的是UTF-8编码,而不是使用Java Character类的UTF-16编码。
Java Character类采用遵循Unicode Standard version 4的UTF-16编码[1],每个字符采用定长的16位(两个字节)进行编码,对于代码点高于Basic Multilingual Plane(BMP,代码点U+0000~U+FFFF)的增补字符,采用两个代理字符进行表示。
Text类采用的UTF-8编码,使用变长的1~4个字节对字符进行编码。对于ASCII字符只使用1个字节,而对于High ASCII和多字节字符使用2~4个字节表示,我想Hadoop在设计时选择使用UTF-8而不是String的UTF-16就是基于上面的原因,为了节省字节长度/空间的考虑。
由于Text采用的是UTF-8编码,所以Text类没有提供String那样多的操作,并且在操作Text对象时,比如Indexing和Iteration,一定要注意这个区别,不过我们建议在进行Text操作时,如果可能可以将Text对象先转换成String,再进行操作。
Text类的字节序列表示为一个VIntWritable + UTF-8字节流,VIntWritable为整个Text的字符长度,UTF-8字节数组为真正的Text字节流。具体请看下面的代码片段:
1 |
|
程序输出:
Byte array per Text("my text") is: \
076d792074657874 with length: 8
Byte array per Text("我的文本") is: \
0ce68891e79a84e69687e69cac with length: 13
在上面的输出中,首个字节代表的该段Text/文本的长度,在UTF-8编码下“my text”占用的字节长度为7个字节(07),而中文“我的文本”的字节长度是12个字节(0c)。
定制Writable类的字节序列
本节中我们将使用上篇文章中的MyWritable类进行说明,回顾一下,MyWritable是一个由两个VLongWritable类构成的定制化Writable类型。
1 |
|
程序输出:
Byte array per MyWritable(1000, 1000000000) is: \
8e03e88c3b9aca00 with length: 8
从输出我们可以很清楚的看到,定制的Writable类的字节序列实际上就是基本Writable类型的组合,输出“8e03e88c3b9aca00”的前三个字节是1000的VLongWritable的字节序列,“8c3b9aca00”是1000000000VLongWritable的字节序列,这一点可以从我们编写的MyWritable类的write方法中找到答案:
1 |
|
总结
本文通过实例介绍了Hadoop Writable类序列化时占用的字节长度,并分析了Writable类序列化后的字节序列的结构。需要注意的是Text类为了节省空间的目的采用了UTF-8的编码,而不是Java Character的UTF-16编码,自定义的Writable的字节序列与该Writable类的write()方法有关。
最后指出,Writable是Hadoop序列化的核心,理解Hadoop Writable的字节长度和字节序列对于选择合适的Writable对象以及在字节层面操作Writable对象至关重要。
参考资料
Tom White, Hadoop: The Definitive Guide, 3rd Edition
---EOF---
Hadoop序列化与Writable接口(二)的更多相关文章
- Hadoop序列化与Writable接口(一)
Hadoop序列化与Writable接口(一) 序列化 序列化(serialization)是指将结构化的对象转化为字节流,以便在网络上传输或者写入到硬盘进行永久存储:相对的反序列化(deserial ...
- Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable
酒,是个好东西,前提要适量.今天参加了公司的年会,主题就是吃.喝.吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个喷子!在大家推杯换盏之际,难免一些画面浮现脑 ...
- Hadoop中序列化与Writable接口
学习笔记,整理自<Hadoop权威指南 第3版> 一.序列化 序列化:序列化是将 内存 中的结构化数据 转化为 能在网络上传输 或 磁盘中进行永久保存的二进制流的过程:反序列化:序列化的逆 ...
- hadoop中的序列化与Writable接口
本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-interface.html,转载请注明源地址. 简介 序列化和反序列化就是结构化对象 ...
- Hadoop序列化
遗留问题: Hadoop序列化可以复用对象,是在哪里复用的? 介绍Hadoop序列化机制 Hadoop序列化机制详解 Hadoop序列化的核心 Hadoop序列化的比较接口 ObjectWrita ...
- Hadoop基础-序列化与反序列化(实现Writable接口)
Hadoop基础-序列化与反序列化(实现Writable接口) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.序列化简介 1>.什么是序列化 序列化也称串行化,是将结构化 ...
- Hadoop Serialization hadoop序列化详解(最新版) (1)【java和hadoop序列化比较和writable接口】
初学java的人肯定对java序列化记忆犹新.最开始很多人并不会一下子理解序列化的意义所在.这样子是因为很多人还是对java最底层的特性不是特别理解,当你经验丰富,对java理解更加深刻之后,你就会发 ...
- 为什么hadoop中用到的序列化不是java的serilaziable接口去序列化而是使用Writable序列化框架
继上一个模块之后,此次分析的内容是来到了Hadoop IO相关的模块了,IO系统的模块可谓是一个比较大的模块,在Hadoop Common中的io,主要包括2个大的子模块构成,1个是以Writable ...
- eclipse 提交作业到JobTracker Hadoop的数据类型要求必须实现Writable接口
问:在eclipse中的写的代码如何提交作业到JobTracker中的哪?答:(1)在eclipse中调用的job.waitForCompletion(true)实际上执行如下方法 connect() ...
随机推荐
- Python3 学习第十四弹: 模块学习六之re模块 + 正则表达式 (转)
本文转自 AstralWind 的博客:Python正则表达式指南 特来收藏 1. 正则表达式基础 1.1. 简单介绍 正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强大工具,拥有 ...
- iptables详解(6):iptables扩展匹配条件之’–tcp-flags’
如果你看过前文,那么你一定知道,前文已经对"tcp扩展模块"做过总结,但是只总结了tcp扩展模块中的"--sport"与"--dport"选 ...
- bzip2压缩 解压缩
压缩/解压缩压缩/解压缩之后的文件名称 必须是bz2 首先是 -z 压缩文件-d 解压缩!
- progressbar进度条组件
Progressbar 进度条组件 通过$.fn.progressbar.fn.defaults重写默认的defaults进度条(progressbar)提供了一种显示长时间操作进度的反馈.进度可被更 ...
- JUnit出错,却没有显示任何报错信息【待解答】
JUnit测试代码如下: 原因分析: JUnit测试单元里,测试函数好像不能带参数? 解决办法: 发现测试函数testBookShopDaoUpdateBookStock(int isbn)里的参数i ...
- ajaxFileUpload的data数据带pre标签
解决办法: var ret = jQuery.parseJSON(jQuery(data).text());
- Linux:grep命令详解
grep grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具, ...
- 利用 squid 反向代理提高网站性能(转载)
本文在介绍 squid 反向代理的工作原理的基础上,指出反向代理技术在提高网站访问速度,增强网站可用性.安全性方面有很好的用途.作者在具体的实验环境下,利用 DNS 轮询和 Squid 反向代理技术, ...
- for循环打印等腰三角形、直角三角形、菱形
一.等腰三角形 package s1; import java.util.Scanner; public class C31 { public static void main(String[] ar ...
- Spring核心概念(一)
1.解决JavaEE的轻量级框架. 2.环境搭建 第一步:导入spring的jar包 第二步:导入配置文件(一般写在resource下面) 第三步:创建一个类(bean) 第四步:在主配置文件中注入这 ...