序列化框架

除了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. K最近邻算法项目实战

    这里我们用酒的分类来进行实战练习 下面来代码 1.把酒的数据集载入到项目中 from sklearn.datasets import load_wine #从sklearn的datasets模块载入数 ...

  2. 清北学堂-DAY2-数论专题-中国剩余定理(CRT)

    首先请看定义:(百科上抄下来的)孙子定理是中国古代求解一次同余式组(见同余)的方法.是数论中一个重要定理.又称中国余数定理. 一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作&l ...

  3. FastDFS高可用集群架构配置搭建及使用

    一,概述FastDFS 是一个开源的高性能分布式文件系统(DFS). 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡.FastDFS 系统有三个角色:跟踪服务器(Tracker ...

  4. iOS8中UIActionSheet弹出UIImagePickerController异常处理

    iOS8之后,UIActionSheet改父于UIAlertController.带来了一丢丢兼容性的问题. 比如在弹出的actionsheet中选择从相册选择图片或者拍照,之后弹出UIImagePi ...

  5. How to find Oracle EBS Weblogic Server Admin Port and URL

    How to find Oracle EBS Weblogic Server Admin Port and URL   Weblogic admin portMethod 1 Open the App ...

  6. Java发送email的端口问题

    Could not connect to SMTP host: smtp.***.com, port: 465, response: -1 使用Java发送email 的端口问题.一般使用25端口即可 ...

  7. Linux命令——cat、more、less、head、tail

    cat 一次显示整个文件 -n:显示行号 -b :和 -n 相似,只不过对于空白行不编号 -s:当遇到有连续两行以上的空白行,就代换为一行的空白行 -E显示换行符 [root@localhost ~] ...

  8. Python多线程爬虫爬取网页图片

    临近期末考试,但是根本不想复习!啊啊啊啊啊啊啊!!!! 于是做了一个爬虫,网址为 https://yande.re,网页图片为动漫美图(图片带点颜色........宅男福利 github项目地址为:h ...

  9. vue 有条件加载组件 执行某方法后再渲染组件

    <component :is="currentCom"></component>   import Grid from './component/grid' ...

  10. WCF双通信

    请求过程中的回调 这是一种比较典型的双工消息交换模式的表现形式,客户端在进行服务调用的时候,附加上一个回调对象:服务在对处理该处理中,通过客户端附加的回调对象(实际上是调用回调服务的代理对象)回调客户 ...