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() ...
随机推荐
- MongoHelper.cs
using System; using MongoDB.Bson; using MongoDB; using System.Web; using MongoDB.Driver; namespace Y ...
- redis高级应用特征
Redis高级应用特性 1.安全性 2.主从复制 3.事务处理 4.持久化机制 5.发布订阅消息 6.虚拟内存的使用 安全性 设置客户端连接后进行任何其他指定前需要使用的密码. 警告:因为redis速 ...
- Linux:history命令详解
Linux下History命令 主要用于显示历史指令记录内容, 下达历史纪录中的指令 . 语法 history [n] history [-c] history [-raw] histfiles ...
- phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接
phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接--解决方法 phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接.您应该检查配置文件中的主机.用户名和 ...
- (转)MapReduce Design Patterns(chapter 6 (part 1))(十一)
Chapter 6. Metapatterns 这种模式不是解决某个问题的,而是处理模式的关系的.可以理解为“模式的模式”.首先讨论的是job链,把几个模式联合起来解决复杂的,有多个阶段要处理的问题. ...
- echarts-detail---散点图
data4 = [{ xAxis: result.AvgEvaluate, seriesId: ', name: '基干360综合分' }, { yAxis: evalue, seriesId: ', ...
- html与css与JavaScript的关系
“HTML是网页的结构,CSS是网页的外观,而JavaScript是页面的行为.” 1)HTML—Hypertext Markup Language. 超文本标记语言.用来描述网页的语言. <h ...
- 《利用Python进行数据分析》笔记---第2章--来自bit.ly的1.usa.gov数据
写在前面的话: 实例中的所有数据都是在GitHub上下载的,打包下载即可. 地址是:http://github.com/pydata/pydata-book 还有一定要说明的: 我使用的是Python ...
- 全新Wijmo5中文学习指南正式上线
Wijmo 是一款使用 TypeScript 编写的新一代 JavaScript/HTML5 控件集.它秉承触控优先的设计理念,在全球率先支持 AngularJS,并且支持React.VueJS以及T ...
- 使用json path设置关联
与正则表达式相比,这种方法会更简单一些: json path是在返回的是K-V的格式中根据key进行的关联,如果压的接口返回的是json的话,使用json path比较方便,如果不是json的话,就使 ...