一、关于序列化:
序列化,可以存储“活的”( 只生存在内存里,关机断电就没有了,一般只能由本地的进程使用,而不能被发送到网络上的另外一台计算机)对象,可以将“活的”对象发送到远程计算机。
而把“活的”对象序列化,就是把“活的”对象转化成一串字节,而“反序列化”,就是从一串字节里解析出“活的”对象。于是,如果想把“活的”对象存储到文件,存储这串字节即可,如果想把“活的”对象发送到远程主机,发送这串字节即可,需要对象的时候,做一下反序列化,就能将对象“复活”了。
将对象序列化存储到文件,术语又叫“持久化”。将对象序列化发送到远程计算机,术语又叫“数据通信”。
序列化的目的:
- 进程间的通信
- 数据持久性存储
二、HADOOP的序列化:
hadoop在节点间的内部通讯使用的是RPC,RPC协议把消息翻译成二进制字节流发送到远程节点,远程节点再通过反序列化把二进制流转成原始的信息。RPC的序列化需要实现以下几点:
1.压缩,可以起到压缩的效果,占用的宽带资源要小。
2.快速,内部进程为分布式系统构建了高速链路,因此在序列化和反序列化间必须是快速的,不能让传输速度成为瓶颈。
3.可扩展的,新的服务端为新的客户端增加了一个参数,老客户端照样可以使用。
4.兼容性好,可以支持多个语言的客户端
在hadoop中,序列化处于核心地位。因为无论是存储文件还是在计算中传输数据,都需要执行序列化的过程。序列化和反序列化的速度、序列化后的数据大小都会影响数据传输的速度,以致影响计算的效率。
为什么不使用java序列化?
- java的序列化机制在每个类的对象第一次出现的时候保存了每个类的信息,比如类名,第二次出现的类对象会有一个类的reference,导致空间的浪费。
- 有成千上万(打个比方,不止这么多)的对象要反序列化, 而java序列化机制不能复用对象, java反序列化的时候, 每次要构造出新的对象,在hadoop的序列化机制中, 反序列化的对象是可以复用的。
- java序列化不够灵活,hadoop自己写序列化很容易,而java不是。
下面介绍下Hadoop的序列化机制:
Writable类:
Writable是Hadoop的核心,Hadoop通过它来定义了Hadoop中基本的数据类型及其操作。Writable类也就是org.apache.hadoop.io.Writable接口,Hadoop的所有可序列化对象都必须实现这个接口,Hadoop中的key和value必须是实现了Writable接口的对象,以支持在MapReduce任务中的序列化和反序列化。Writable接口里有两个方法,一个是write方法,将对象写入字节流,另一个是readFields方法,从字节流解析出对象。下面是Writable类得层次结构:
从上图中,我们可以看到如BooleanWritable、ByteWritable等类不是直接继承自Writable类,而是继承自WritableComparable类,WritableComparable是Hadoop中非常重要的接口类,WritableComparable接口是可序列化并且可比较的接口,MapReduce中所有的key值类型都必须实现这个接口,既然是可序列化的那就必须得实现readFiels()和write()这两个序列化和反序列化函数,既然也是可比较的那就必须得实现compareTo()函数,该函数即是比较和排序规则的实现,这样MR中的key值就既能可序列化又是可比较的,那么Hadoop为什么中的MR的Key值为什么是可比较的?Hadoop又是如何实现比较器的呢?带着这两个问题,接下来介绍下Hadoop的比较器。
<一>、Hadoop的比较器
大家都知道,MapReduce在执行时,Reducer(执行reduce任务的机器)会收集相同KEY值的 key/value对,并且在reduce之前会有一个排序过程,排序是MapReduce的核心技术,尽管应用程序本身不需要对数据排序,但可以使用MapReduce的排序功能来组织数据。WritableComparable的比较器是由WritableComparator来实现的,MR键值的比较都是通过对WritableComparator类型来进行比较,类图如下:
从类图中,我们也可以看到WritableComparator实现了RawComparator接口类,RawComparator类定义了对未反序列化对象的读取,可直接用于序列化字节间的比较的方法,这样做有什么好处?大家都知道Hadoop多个节点上的进程间通信是通过远程过程调用RPC实现的,而RPC协议会将消息序列化为二进制流后再发送到远程节点,远程节点接收到二进制流后再反序列化为原始消息,如果对序列化的二进制流直接比较则会提高效率,避免了创建对象的开销。
RawComparator接口的唯一方法是int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2),其中b1为第一个对象所在的字节数组,s1为该对象在b1中的起始位置,l1为对象在b1中的长度,b2为第一个对象所在的字节数组,s2为该对象在b2中的起始位置,l2为对象在b2中的长度。WritableComparator类是RawComparator的子类,用于比较实现了WritableComparable接口的对象。基本的实现是按照自然顺序进行比较,若想按照其它顺序比较,比如逆序,可以继承该类并覆盖compare(WritableComparable,WritableComparable)来实现定制的比较器。这是因为在针对字节的compare方法中,最终调用了compare(WritableComparable,WritableComparable)方法,因此该方法决定了按照什么方式进行比较。可以通过覆盖compare(byte[],int,int,byte[],int,int)优化比较操作,该类提供了许多静态方法以帮助该方法的优化实现。
实现代码如下:
@Override
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
try {
buffer.reset(b1, s1, l1); // parse key1
key1.readFields(buffer);
buffer.reset(b2, s2, l2); // parse key2
key2.readFields(buffer);
} catch (IOException e) {
throw new RuntimeException(e);
}
return compare(key1, key2); // compare them
}
<二>、Writable类中的基本数据类型
Writable中封装有很多JAVA的基本类,如图:
Java基本类型 |
Writable |
布尔型(Boolean) |
BooleanWritable |
字节型(byte) |
ByteWritable |
整型(int) |
IntWritable VIntWritable |
浮点型(float) |
FloatWritable |
长整型(long) |
LongWritable VLongWritable |
双精度浮点型(double) |
DoubleWritable |
Hadoop还自定义了两个变长的类型,VIntWritable和VLongWritable,Hadoop对于VLong类型的处理方法的实现得比较巧妙:
具体代码如下:
上面代码的意思是如果数值比较小(在-112和127之间),那么就直接将这个数值写入数据流中。如果不是,则先用len表示字节长度与正负,并写入数据流中,然后在其后写入这个数值。比较费脑,有兴趣的同学可详细看下。
下面再介绍几个Hadoop常用的Writable类型:
(1)Text类:
Text类是针对UTF-8序列(UTF-8是UNICODE的一种变长字节字符编码,又称万国码)的Writable类,一般认为他等价与java.lang.String的Writable类。但是他和String还是有一些差异的。Text的索引是按编码后字节序列中的位置来实现的,String是按其所包含的char编码单元来索引的。看下面的例子:
String s=String("\u0041\u00df\uu6671\ud801\uDc00");
Text t=Text("\u0041\u00df\uu6671\ud801\uDc00");
s.indexof("\u0041")==0 t.find("\u0041")==0
s.indexof("\u00df")==1 t.find("\u00df")==1
s.indexof("\u6671")==2 t.find("\u6671")==3
s.indexof("\ud801\uDc00")==3 t.find(\ud801\uDc00")==6
s.length()==5 s.getBytes("UTF-8").length()==10
t.getLength()==10(1+2+3+4)
通过字节偏移量来进行位置索引,实现对Text类的Unicode字符迭代是非常复杂的,因为不能简单的通过增加位置的索引值来实现。所以必先将Text对象转化为java.nio.BytesBuffer对象,然后利用缓冲区对Text对象反复调用bytesToCodePoint()静态方法,该方法能获取下一代码的位置。
由于Text类不像java.lang.String类那样有丰富的字符串操作API,所以在一些情况下为了方便处理,需要将Text类转化为String类,这一过程通过toString来实现。
(2)ByteWritable类,二进制数据数组的封装,它的序列化格式为一个用于指定后面数据字节数的整数域(4字节),后跟字节本身。
(3)NullWritabe,是Writable的一个特殊类型,它的序列化长度为0,类似于null。
(4)ObjectWritable类,是对java基本类型(String,enum,Writable,null或这些类型组成的数组)的一个通用封装。
(5)Writable集合类,共有4个集合类,其中ArrayWritable是对Writable的数组的实现,TwoDArrayWritable是对Writable的二维数组的实现,MapWritable是对Map的实现,SortedMapWritable是对SortedMap的实现。
(6)定制的Writable类,我们可以根据自己的需求构造自己的Writable类,可以根据需要控制二进制表示和排序顺序,由于Writable是MapReduce数据路径的核心,所以调整二进制表示能对性能残生显著效果。
三、总结:
Hadoop的序列化机制非常简单直接,并不像JAVA的序列化那样面面俱到,这样可以使数据更加紧凑,同时也可以加快序列化和反序列化的速度。
相关推荐
Hadoop 3.x(MapReduce)----【Hadoop 序列化】---- 代码 Hadoop 3.x(MapReduce)----【Hadoop 序列化】---- 代码 Hadoop 3.x(MapReduce)----【Hadoop 序列化】---- 代码 Hadoop 3.x(MapReduce)----【Hadoop ...
4. **数据存储与序列化**:Hadoop使用`org.apache.hadoop.io`包处理数据的存储和序列化,包括各种基本类型(如IntWritable、Text等)和复杂的可序列化对象(如SequenceFile、Avro等)。 5. **配置管理**:`org....
- 共享库:包含各种实用工具,如压缩、加密和序列化。 2. HDFS概述 Hadoop分布式文件系统(HDFS)是Hadoop生态中的关键组件,它设计为在大量廉价硬件上运行,提供了高吞吐量的数据访问。HDFS遵循主从架构,由...
在这里,用户可以找到CASMI-I/O项目的源码,以便学习、定制或者与其他Hadoop组件集成。 总结这些知识点,我们可以得出以下要点: 1. Hadoop YARN是一个分布式资源管理系统,用于协调Hadoop集群中的计算任务。 2. ...
4. **I/O工具**:提供了一系列高效的输入/输出工具,如压缩和解压缩库,以及序列化框架。 5. **配置管理**:通过Properties和Configuration类来管理和加载Hadoop集群的配置信息。 6. **日志和监控**:支持日志聚合...
Apache HBase是一个基于Hadoop的分布式列族数据库,它针对大规模结构化数据提供高可靠性、高性能、可伸缩的实时读写访问。HBase的设计灵感来源于Google的BigTable,采用了一个增强的稀疏排序映射表的数据模型,键由...
在Hadoop中,JNI用于调用C/C++编写的本地库,以提高性能,例如在I/O操作、数据压缩和网络通信中。 2. **libhadoop.so**:这是Hadoop的核心本地库,包含了Hadoop的系统级功能,如内存管理、线程支持、文件系统操作等...
- **序列化**:介绍了Hadoop中序列化框架的作用,以及它们如何简化对象的传输和存储。 - **基于文件的数据结构**:讲解了Hadoop中如何使用特定的数据结构来优化数据的读写操作。 #### 六、MapReduce应用开发 - **...
标题中的“Hadoop序列化机制”是指Hadoop生态系统中用于数据传输和存储的数据表示方式,它是Hadoop MapReduce和Hadoop Distributed File System (HDFS)等组件之间交换数据的关键技术。序列化是将对象转化为可存储或...
- **I/O 模块**:提供多种输入/输出格式,序列化工具和压缩算法。 - **安全服务**:包括认证、授权和加密功能,支持 Kerberos 等安全协议。 - **文件系统抽象**:允许与多种类型的文件系统(包括本地文件系统和 HDFS...
hbase-annotations.jar、hbase-shaded-netty.jar和hbase-shaded-protobuf.jar是HBase的组成部分,它们分别提供了注解支持、网络通信库和序列化协议缓冲区的封装。 Hive是基于Hadoop的数据仓库工具,可以将结构化的...
这些依赖涵盖了各种库、工具和其他开源项目,如Apache Commons、Zookeeper、protobuf等,它们为Hadoop提供了网络通信、序列化、配置管理等功能支持。 1. **依赖环境**:Hadoop的编译环境通常要求Java开发环境(JDK...
- 序列化是数据交换的关键,Hadoop支持多种序列化格式。 - 基于文件的数据结构如SequenceFile和Avro,方便高效地存储和处理结构化和半结构化数据。 5. **MapReduce应用开发** - 开发MapReduce作业需要配置API,...
4. **Hadoop的I/O** - **数据完整性**:HDFS通过校验和确保数据的完整性。 - **压缩**:提高存储效率和传输速度。 - **序列化**:数据交换的关键,支持多种序列化框架。 - **基于文件的数据结构**:如...
- **I/O工具**:如序列化框架、压缩算法和输入/输出流的实现,提高了数据处理效率。 - **安全框架**:包括认证、授权和审计机制,确保Hadoop集群的安全性。 - **配置管理**:提供了一套完整的配置文件,用于管理...
5. **lib**目录:包含了Hadoop依赖的第三方库文件,这些库支持Hadoop的各种功能,如网络通信、序列化和XML解析等。 6. **build**和**src**目录:构建脚本和源代码分别位于这两个目录中。通过构建脚本(通常是Ant或...
4. **I/O工具**:Hadoop提供了一系列的输入/输出工具,如序列化框架(Writables和Protobufs)、压缩算法(Gzip、BZip2、Lzo、Snappy等)以及数据分块处理机制。 5. **内存管理**:Hadoop通过YARN(Yet Another ...
在执行Hadoop数据迁移时,Hadoop集群中的MapReduce作业会利用JDBC驱动与Oracle数据库建立连接,通过执行SQL查询来检索数据,并使用Hadoop的序列化机制将数据写入到HDFS。这样,Oracle中的数据就成功地迁移到了Hadoop...