序列化框架

除了writable实现序列化之外,只要实现让类型和二进制流相互转换,都可以作为hadoop的序列化类型,为此Hadoop提供了一个序列化框架接口,他们在org.apache.hadoop.io.serializer包中,Writable可以作为MapReduce支持的类型也是因为实现了这个框架接口。使用流程是定义序列化类实现框架接口->io.serializations参数配置序列化类名称,用一个逗号隔开的类名列表—> SerializationFactory构造函数中会读取配置,根据反射机制和类名创建序列化对象,保存在队列中—>通过SerializationFactory的函数getSerializer(Class<T> c)获取入序列化对象,入参是要获取对象的类名称。

在先来看看序列化开接口,以及writable是怎么实现的。

(1)序列化接口Serializer

打开流,序列化,关闭流

public interface Serializer <T>  {

void open(java.io.OutputStream outputStream) throws java.io.IOException;

void serialize(T t) throws java.io.IOException;

void close() throws java.io.IOException;

}

(2)反序列化接口:Deserializer

定义了一组接口,打开流,反序列化,关闭流

public interface Deserializer <T>  {

void open(java.io.InputStream inputStream) throws java.io.IOException;

T deserialize(T t) throws java.io.IOException;

void close() throws java.io.IOException;

}

(3)序列化判断和实例获取接口

Accept函数判断是否支持序列化,要求是writable的子类,getSerializer函数返回序列化的实例,getDeserializer获取反序列化实例。通过实例调用接口函数去实现序列化函数。

public interface Serialization <T>  {

boolean accept(java.lang.Class<?> aClass);

org.apache.hadoop.io.serializer.Serializer<T> getSerializer(java.lang.Class<T> tClass);

org.apache.hadoop.io.serializer.Deserializer<T> getDeserializer(java.lang.Class<T> tClass);

}

(4)定义序列化类

Writable定义序列化类要实现上面的三个接口, 实现接口中的序列化和反序列化函数。

public class WritableSerialization extends Configured

implements Serialization<Writable> {

//定义静态反序列化类

static class WritableDeserializer extends Configured

implements Deserializer<Writable> {

private Class<?> writableClass;

private DataInputStream dataIn;

//定义构造函数

public WritableDeserializer(Configuration conf, Class<?> c) {

setConf(conf);

this.writableClass = c;

}

//打开输入流

public void open(InputStream in) {

if (in instanceof DataInputStream) {

dataIn = (DataInputStream) in;

} else {

dataIn = new DataInputStream(in);

}

}

//反序列化函数,读取数据

public Writable deserialize(Writable w) throws IOException {

Writable writable;

if (w == null) {

writable

= (Writable) ReflectionUtils.newInstance(writableClass, getConf());

} else {

writable = w;

}

writable.readFields(dataIn);

return writable;

}

//关闭输入流

public void close() throws IOException {

dataIn.close();

}

}

序列化类

static class WritableSerializer implements Serializer<Writable> {

private DataOutputStream dataOut;

//打开输出流

public void open(OutputStream out) {

if (out instanceof DataOutputStream) {

dataOut = (DataOutputStream) out;

} else {

dataOut = new DataOutputStream(out);

}

}

序列化函数写入数据

public void serialize(Writable w) throws IOException {

w.write(dataOut);

}

//关闭输出流

public void close() throws IOException {

dataOut.close();

}

}

//判断是否是writable的子类

public boolean accept(Class<?> c) {

return Writable.class.isAssignableFrom(c);

}

//返回反序列化对象

public Deserializer<Writable> getDeserializer(Class<Writable> c) {

return new WritableDeserializer(getConf(), c);

}

//返回序列化对象

public Serializer<Writable> getSerializer(Class<Writable> c) {

return new WritableSerializer();

}

}

(5)序列化工厂

public class SerializationFactory extends Configured {

private static final Log LOG = LogFactory.getLog(SerializationFactory.class.getName());

private List<Serialization<?>> serializations = new ArrayList();

public SerializationFactory(Configuration conf) {

super(conf);

//通过读取配置信息conf中的io.serializations参数来确定Serializations,这个参数是一个逗号隔开的类名列表

String[] arr$ = conf.getStrings("io.serializations", new String[]{WritableSerialization.class.getName(), //默认包含Writable和Avro

AvroSpecificSerialization.class.getName(), AvroReflectSerialization.class.getName()});

int len$ = arr$.length;

for(int i$ = 0; i$ < len$; ++i$) {

String serializerName = arr$[i$];

this.add(conf, serializerName);

}

}

//添加到list的函数

private void add(Configuration conf, String serializationName) {

try {

Class<? extends Serialization> serializionClass = conf.getClassByName(serializationName);

//根据类名和反射机制创建序列化对象,保存到  serializations的List中

this.serializations.add((Serialization)ReflectionUtils.newInstance(serializionClass, this.getConf()));

} catch (ClassNotFoundException var4) {

LOG.warn("Serialization class not found: ", var4);

}

}

public <T> Serializer<T> getSerializer(Class<T> c) {

Serialization<T> serializer = this.getSerialization(c);

return serializer != null ? serializer.getSerializer(c) : null;

}

public <T> Deserializer<T> getDeserializer(Class<T> c) {

Serialization<T> serializer = this.getSerialization(c);

return serializer != null ? serializer.getDeserializer(c) : null;

}

public <T> Serialization<T> getSerialization(Class<T> c) {

Iterator i$ = this.serializations.iterator();

Serialization serialization;

do {

if (!i$.hasNext()) {

return null;

}

serialization = (Serialization)i$.next();

} while(!serialization.accept(c));

return serialization;

}

}

其他序列化框架对比

ObjectInput(Out)Stream

1.无法跨语言。内部私有的协议, 2.序列后的码流太大。java序列化的大小是二进制编码的5倍多!
3.序列化性能太低。java序列化的性能只有二进制编码的6.17倍。

google的Protobuf

1.结构化数据存储格式(xml,json等)
2.高性能编解码技术
3.语言和平台无关,扩展性好
4.支持java,C++,Python三种语言。protostuff也许是最佳选择。protostuff相比于kyro还有一个额外的好处,就是如果序列化之后,反序列化之前这段时间内,java
class增加了字段(这在实际业务中是无法避免的事情),kyro就废了。

但是protostuff只要保证新字段添加在类的最后,而且用的是sun系列的JDK, 是可以正常使用的。

faceBook的Thrift

1.Thrift支持多种语言(C++,C#,Cocoa,Erlag,Haskell,java,Ocami,Perl,PHP,Python,Ruby,和SmallTalk)
2.Thrift适用了组建大型数据交换及存储工具,对于大型系统中的内部数据传输,相对于Json和xml在性能上和传输大小上都有明显的优势。
3.Thrift支持三种比较典型的编码方式。(通用二进制编码,压缩二进制编码,优化的可选字段压缩编解码)

Kryo

1.速度快,序列化后体积小
2.跨语言支持较复杂

hessian

1.默认支持跨语言
2.较慢

fst

fst是完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍,大小是JDK大小的1/3左右。

Gson

Gson是目前功能最全的Json解析神器, Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。

FastJson

Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。无依赖,不需要例外额外的jar,能够直接跑在JDK上。FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。

引用:

https://www.jianshu.com/p/937883b6b2e5

https://www.helplib.com/Java_API_Classes/article_62465

https://blog.csdn.net/lipeng_bigdata/article/details/51202764

自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

https://www.cnblogs.com/bclshuai/p/11380657.html

5.3.4 Hadoop序列化框架的更多相关文章

  1. hadoop深入研究:(十三)——序列化框架

    hadoop深入研究:(十三)--序列化框架 Mapreduce之序列化框架(转自http://blog.csdn.net/lastsweetop/article/details/9376495) 框 ...

  2. hadoop压缩框架

    一般来说,计算机处理的数据都存在一些冗余度,同时数据中间,尤其是相邻数据间存在着相关性,所以可以通过一些有别于原始编码的特殊编码方式来保存数据,使数据占用的存储空间比较小,这个过程一般叫压缩.和压缩对 ...

  3. Hadoop的简单序列化框架

    Hadoop提供了一个加单的序列化框架API,用于集成各种序列化实现.该框架由Serialization实现. 其中Serialization是一个接口,使用抽象工厂的设计模式,提供了一系列和序列化相 ...

  4. 为什么hadoop中用到的序列化不是java的serilaziable接口去序列化而是使用Writable序列化框架

    继上一个模块之后,此次分析的内容是来到了Hadoop IO相关的模块了,IO系统的模块可谓是一个比较大的模块,在Hadoop Common中的io,主要包括2个大的子模块构成,1个是以Writable ...

  5. Mapreduce之序列化框架(转自http://blog.csdn.net/lastsweetop/article/details/9376495)

    框架简介 MapReduce仅仅可以支持Writable做key,value吗?答案是否定的.事实上,一切类型都是支持的,只需满足一个小小的条件:每个类型是以二进制流的形式传输.为此Hadoop提供了 ...

  6. 踏着前人的脚印学Hadoop——序列化,Writerable

    package org.apache.hadoop.io; import java.io.DataOutput;import java.io.DataInput;import java.io.IOEx ...

  7. java序列化是什么和反序列化和hadoop序列化

    1.什么是序列化和系列化DE- 神马是序列化它,序列化是内存中的对象状态信息,兑换字节序列以便于存储(持久化)和网络传输.(网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什 ...

  8. Hadoop序列化与Java序列化

    序列化就是把内存中的对象的状态信息转换成字节序列,以便于存储(持久化)和网络传输 反序列化就是就将收到的字节序列或者是硬盘的持久化数据,转换成内存中的对象. 1.JDK的序列化 只要实现了serial ...

  9. Hadoop序列化机制及实例

    序列化 1.什么是序列化?将结构化对象转换成字节流以便于进行网络传输或写入持久存储的过程.2.什么是反序列化?将字节流转换为一系列结构化对象的过程.序列化用途: 1.作为一种持久化格式. 2.作为一种 ...

随机推荐

  1. ELK日志分析系统的搭建

    一.ELK简介 ELK是Elasticsearch.Logstash.Kibana的简称,这三者是核心组件. Elasticsearch是数据存储.搜索.分析引擎,功能非常强大:Logstash是日志 ...

  2. Python练习_文件操作_day8

    1. 1.作业 1,有如下文件,a1.txt,里面的内容为: 老男孩是最好的学校, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读出来并 ...

  3. maccms代码审计

    由于工作原因,分析了很多的cms也都写过文章,不过觉得好像没什么骚操作都是网上的基本操作,所以也就没发表在网站上,都保存在本地.最近突然发现自己博客中实战的东西太少了,决定将以前写的一些文章搬过来,由 ...

  4. Go 函数编程

    函数的声明 在 Go 语言中,函数声明通用语法如下: func functionname(parametername type) returntype { // 函数体(具体实现的功能) } 函数的声 ...

  5. URL - Fiddler - IIS

    URL和URI URI:Uniform Resource Identifier,唯一标识一个网络资源 URL:Uniform Resource Locator,指向网络资源地址 URL是URI的子集, ...

  6. IBM XIV

    参考:https://www.doit.com.cn/p/author/xigua 参考:http://www.doit.com.cn/p/196056.html 图片说明: IBM XIV存储系统采 ...

  7. vccode配置c++ 编译环境

    https://blog.csdn.net/qq_43041976/article/details/88544632 https://www.cnblogs.com/bpf-1024/p/115970 ...

  8. 一个基于TCP/IP的小项目,实现广播消息的功能。(超详细版)

    1.结合现状 功能分析 该功能基于上个项目的改进,主要是通过对服务器端代码的修改,以及对客户端作少许修改,实现开启多客户端时,一个客户端发送消息,达到对所有客户端广播的效果.可参考网吧里的点歌系统,比 ...

  9. ansible的安装和简单使用

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具的优点,实现了批量系统配置.批量程序部署.批量运行命令等功能.ansible是基于模块工作的,本身没有批量部署的能力.真 ...

  10. C# 操作文件夹、文件

    Form namespace FileProperties { public partial class Form1 : Form { private string currentFolderPath ...