Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable

  酒,是个好东西,前提要适量。今天参加了公司的年会,主题就是吃、喝、吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个喷子!在大家推杯换盏之际,难免一些画面浮现脑海,有郁闷抓狂的,有出成果喜极而涕的,有不知前途在哪儿的迷茫与不安……总的来说,近一年来,不白活,不虚度,感触良多,不是一言两语能说得清道的明的,有时间可以做个总结,下面还是言归正传谈技术吧。

上篇在了解了Hadoop的目录和源码结构后,说好的要啃源码的,那就得啃。也感谢一直以来关注我、支持我的网友,您的关注一直都是我默默前行的动力,也是我在这个行业摸打滚爬的精神食粮^_^

  这里,我们主要对于org.apache.hadoop.conf和org.apache.hadoop.io包的部分进行一个解读,主要包含了hadoop的资源配置类Configuration、hadoop的序列化机制、Writable的地位与继承实现关系、常用类解析。

  一、Hadoop资源配置Configuration

  Hadoop没有使用java.util.Properties管理配置文件,其使用了一套独有的配置文件管理系统,并提供自己的API,即使用org.apache.hadoop.conf.Configuration处理配置信息。

  通过org.apache.io.conf包我们可以发现主要包含以下几个接口和类:

Configurable:接口

  方法:setConf()、getConf()

Configured:实现了Configurable的类

  方法:除了实现了Configurable接口中的方法,还有构造函数、用于配置Configuration参数

  Configuration:

  Configuration类用来设定资源文件。资源文件是包含键值对的XML数据,其可以是字符串或是路径。如果是字符串,将会根据字符串代表的文件名到classpath下找,如果是路径,则会直接到本地文件系统查找。

  Hadoop默认是加载两个资源文件:core-default.xml和core-site.xml

  Configuration参数可以声明为final类型,一旦定义为final类型,后面就无法被更改,例子如下:

<property>
    <name>dfs.client.buffer.dir</name>
    <value>/tmp/hadoop/dfs/client</value>
    <final>true</final>
</property>

 主要方法:有添加资源文件addResource、获取属性值get、设置一个键值对set、获取资源文件个数size等。

  二、Hadoop序列化机制

  在进程间传递对象对象持久化存储的时候,就不得不提到序列化以及反序列化,就需要序列化对象成字节流,反之当要将接收到或从磁盘读取的字节流转换为对象,就要进行反序列化。

序列化:把对象转换为字节序列的过程

  反序列化:把字节序列恢复为对象的过程

  下面是传统序列化和反序列化的代码示例:

  MyObject(用于序列化和反序列化的类对象):

public class MyObject  implements Serializable{
	private static final long serialVersionUID = -5809782578272943999L;
	public String name ;
	private int age;
	public String sex;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
}

测试序列化和反序列化代码:

public class MySerializableTest {

	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		SerializeObject();
		MyObject object = Deserialize();
		System.out.println("name:" + object.getName() + "\tage:" + object.getAge() + "\tsex:" + object.getSex());
	}

	private static MyObject Deserialize() throws FileNotFoundException, IOException, ClassNotFoundException {
		ObjectInputStream oi = new ObjectInputStream(new FileInputStream(new File("/usr/local/hadoop-0.20.2/serialize.txt")));
		MyObject object = (MyObject) oi.readObject();
		System.out.println("反序列化成功");
		return object;
	}

	private static void SerializeObject() throws FileNotFoundException, IOException {

		MyObject object = new MyObject();
		object.setName("Jackie");
		object.setAge(25);
		object.setSex("male");
		ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("/usr/local/hadoop-0.20.2/serialize.txt")));
		oo.writeObject(object);
		System.out.println("序列化成功");
		oo.close();
		
	}
}

最终控制台打印信息:

序列化成功
反序列化成功
name:Jackie	age:25	sex:male

注意:一定要在要序列化和反序列化的类上实现标记接口Serializable,否则会报错。

  当然,这不是我们要将的Hadoop的序列化机制,深入研究传统的序列化机制,就会发现这种Java序列化机制有自己的缺陷比如计算开销大、序列化的结果占用空间大等。作为一个分布式集群的代名词,这种缺点是不可饶恕的,在每个节点之间进行RPC通讯时当遇到不可想象的序列化后的对象占用空间,这是一种灾难。所以,Hadoop编写实现了自己的序列化机制。

  三、Writable的家族体系

  Hadoop的序列化要从这个Writable接口说起。

  Writable接口,即org.apache.hadoop.io.Writable接口,整个Hadoop的所有可序列化的对象接口都必须实现Writable接口,该接口的方法很简单,与传统的序列化类神似。一个是write方法,用于将对象写入字节流,一个是readFields方法,用于将字节流读出解析成对象。

  代码示例:

public class MyWritable implements Writable {
       // Some data     
       private int counter;
       private long timestamp;
       
       public void write(DataOutput out) throws IOException {
         out.writeInt(counter);
         out.writeLong(timestamp);
       }
       
       public void readFields(DataInput in) throws IOException {
         counter = in.readInt();
         timestamp = in.readLong();
       }
       
       public static MyWritable read(DataInput in) throws IOException {
         MyWritable w = new MyWritable();
         w.readFields(in);
         return w;
       }
 }

Writable的家族很庞大,主要成员涵盖在下面的一幅图中:

  四、常见类举例

  BytesWritable

  该类实现了WritableComparable、Writable、Comparable。其用于一串字节序列。

  其主要方法除了readFields(DataInput in)、write(DataOutput out)外,还有equals(Object right_obj)、getSize()这样的方法。

 FloatWritable

  该类实现了WritableComparable、Writable、Comparable。用于Float类型的序列化。

  其主要方法有compareTo(Object o)、readFields(DataInput in)、write(DataOutput out)等。

  IOUtils

  该类是I/O操作类。

  主要方法有忽略异常关闭closeable对象cleanup()方法、忽略异常关闭流closeStream()方法、拷贝流copyBytes()方法、循环读取字节流长度readFully()方法等。

  MapFile

  MapFile是一个Map集合,包含两个文件:数据文件(map中的键值对)、索引文件

  索引文件会一次性完全读进内存,所以,键的实现需要尽可能小。

  Map文件是通过有序的添加entries构成的,为维持这么个大数据及,通过在一个有序列表中拷贝先前版本进行更新,并得到最新版本的数据文件。

  Text

  该类存储采用UTF-8编码的文本,其提供了在字节流层面的序列/反序列文本、比较文本的方法。另外其还提供了翻转字符串的方法。

  主要方法有:charAt、clear、decode、encode、find、readFields、write等

  SequenceFiles

  SequenceFiles是由二进制键值对构成的平面文件。

  SequenceFile文件有三个写入类基于SequenceFile.CompressionType压缩键值对

  1.Writer:不压缩

  2.RecordCompressWriter:记录压缩,只压缩value

  3.BlockCompressWriter:块压缩,压缩key和value

  WritableFactory

  该类可以用来创建Writable对象

  对于Hadoop等大数据技术有兴趣的欢迎加群413471695交流讨论^_^

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MasiMaro 的技术博文

windows 纤程

纤程本质上也是线程,是多任务系统的一部分,纤程为一个线程准并行方式调用多个不同函数提供了一种可能,它本身可以作为一种轻量级的线程使用。它与线程在本质上没有区别,...

18020
来自专栏顶级程序员

MySQL 全文索引应用简明教程

本文从以下几个方面介绍下MySQL全文索引的基础知识: MySQL全文索引的几个注意事项 全文索引的语法 几种搜索类型的简介 几种搜索类型的实例 全文索引的几个...

392100
来自专栏Web项目聚集地

手写一个Mybatis框架

在手写自己的Mybatis框架之前,我们先来了解一下Mybatis,它的源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,才能够更深入的理解源...

11220
来自专栏PingCAP的专栏

TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现

PingCAP 发布了 TiDB 的源码阅读系列文章,让我们可以比较系统的去学习了解TiDB的内部实现。最近的一篇《SQL 的一生》,从整体上讲解了一条 SQL...

1.7K100
来自专栏应兆康的专栏

Python Web - Flask笔记5

MySQL Workbench是一款专为MySQL设计的ER/数据库建模工具。它是著名的数据库设计工具DBDesigner4的继任者。你可以用MySQL Wor...

19510
来自专栏码农分享

SQL Server 多表数据增量获取和发布 4

最关键的在于获取捕获表信息(系统表中间_CT结尾的数据)。 根据网上资料查取,找到了获取当前捕获表时间区间范围内数据的方式。 见[SQL Server 多表...

16820
来自专栏灯塔大数据

每周学点大数据 | No.41 join 操作

No.41期 join 操作 Mr. 王:第一个话题就是 join 操作。 join 操作在数据库中还是非常常见的。 小可:这个 join 指的是笛卡儿积操...

39070
来自专栏小白鼠

Mybatis

从xml配置文件中读取配置,然后通过SqlSessionFactoryBuilder构建SqlSessionFactory实例(建造者模式)。SqlSessio...

29830
来自专栏积累沉淀

干货--Hadoop自定义数据类型和自定义输入输出格式整合项目案例

正文开始前 ,先介绍几个概念 序列化 所谓序列化,是指将结构化对象转化为字节流,以便在网络上传输或写到磁盘进行永久存储。 反序列化 是指将字节流转回到结构化...

65860
来自专栏MasiMaro 的技术博文

OLEDB 静态绑定和数据转化接口

OLEDB 提供了静态绑定和动态绑定两种方式,相比动态绑定来说,静态绑定在使用上更加简单,而在灵活性上不如动态绑定,动态绑定在前面已经介绍过了,本文主要介绍OL...

12210

扫码关注云+社区

领取腾讯云代金券