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() ...
随机推荐
- nyoj最少乘法次数——快速幂思想
最少乘法次数 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 给你一个非零整数,让你求这个数的n次方,每次相乘的结果可以在后面使用,求至少需要多少次乘.如24:2*2 ...
- MySQL中文入库问题
中文测试没有问题了,此处bug源于MySQL自身编码的问题,创建数据库默认指定相关编码即可. 创建数据库时,指定utf8编码 CREATE DATABASE mydb DEFAULT CHARACTE ...
- vue项目搭建 (二) axios 封装篇
vue项目搭建 (二) axios 封装篇 项目布局 vue-cli构建初始项目后,在src中进行增删修改 // 此处是模仿github上 bailicangdu 的 ├── src | ├── ap ...
- mysql主从复制跳过错误
mysql主从复制,经常会遇到错误而导致slave端复制中断,这个时候一般就需要人工干预,跳过错误才能继续 跳过错误有两种方式: 1.跳过指定数量的事务: mysql>slave stop; m ...
- nfs的简单搭建与原理
nfs最大的缺点是单点,只能一对一nfs统称存储服务器,放视频图片之类的东西,所以服务器的容量很大数字都是放在数据库里边的, nfs的挂载原理 客户端怎么知道服务端的开启端口? 找rpcbind,再启 ...
- Idea_03_常用快捷键
一.前言 这一节我们来看下Idea的一些常用快捷键 二.常用快捷键 Alt + Enter 有错误.警告时的提示 Ctrl+Shift+R 全局 打开资源 ctrl + F 在当前文件查找或替换 Ct ...
- session、cookie、viewstate
session的用法 定义:保存在服务器内存的数据,sesson 只应该应用在需要跨页面且与每个访问用户相关的变量和对象存储上,session在默认情况下20分钟就过期,在页面之中最好不要过多使用,因 ...
- Django知识点总结
一.什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. web应 ...
- 职责链模式(Chain of Responsibility)
一.责任链模式介绍 责任链模式:将能够处理同一类请求的对象连成一条链,使这些对象都有机会处理请求,所提交的请求沿着链传递.从而避免请求的 发送者和接受者之间的耦合关系.链上的对象逐个判断是否有能力处理 ...
- ElasticSearch自定义分词器
通过mapping中的映射,将&映射成and PUT /my_index?pretty' -H 'Content-Type: application/json' -d' { "set ...