序列化框架

除了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. Nginx与负载均衡

    Nginx,首先是一款轻量级的Web服务器,其特点是占有内存少,并发能力强,大厂用户有:百度.新浪.网易.腾讯等.其次,它是一款反向代理服务器:第三,它还是一款电子邮件(IMAP/POP3)代理服务器 ...

  2. buffer 与 cache 的区别

    Buffer 和 Cache buffer 和 cache 同样作为缓存,他们之间有什么区别呢? 简单来说,buffer 是即将要写入磁盘的缓存,而 cache 是从磁盘中读出来放到缓存的 参考来自: ...

  3. nlopt 二次优化

    /* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math. ...

  4. A*算法与8数字谜题(参见《算法》P226习题2.5.32)

    A*算法的目的是找到一条从起始状态到最终状态的最短路径. 在A*算法中,需要在每个点计算启发函数:f(S) = g(S) + h(S),其中g(S)是从起点到S点的距离,h(S)是对从S点到终点的最短 ...

  5. sql根据一个表查询的数据作为条件查询另一个表

    代码格式如下: ) 要注意的是:in后面的查询语句必须是查询一个字段跟前面的表相对应的.比如要根据订单号orderID,OpenBills 这个表就需要查询到orderID这个字段,BillConsu ...

  6. SAP官方发布的ABAP编程规范

    最近有朋友在公众号后台给我留言,"Jerry啊,你最近写的都是一些SAP研究院里面用到的新技术,能不能写点SAP传统的开发技术比如ABAP相关的东西"? 其实Jerry在刚开始写这 ...

  7. OGG 自动重启脚本

    6-20 * * * /oggdata/log/oggautorestart.sh >/oggdata/log/crontab_oggautorestart.log 2>&1 [说 ...

  8. 搭建KVM环境——06 创建虚拟机

    若转载请于明显处标明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9071181.html 虚拟机磁盘格式 创建一个raw格式的虚拟机磁盘 [root@Cen ...

  9. 服务器IP与个人IP的特点

    服务器IP:系统类型.开放的端口及运行的服务.C段同类机器数量.是否机房.IDC服务商 个人IP:系统类型.开放的端口及运行的服务……

  10. U盘装manjaro 18报Python error in job “initcpio”

    更新: 还是不行,大家再找别的方法. 以下内容仅做参考,意义不大. U盘安装 用rufus做U盘,写入选DD模式,比ISO模式可靠点. 错误解决 报错信息: Error installing Manj ...