框架简介

MapReduce仅仅可以支持Writable做key,value吗?答案是否定的。事实上,一切类型都是支持的,只需满足一个小小的条件:每个类型是以二进制流的形式传输。为此Hadoop提供了一个序列化框架来支持,他们在org.apache.hadoop.io.serializer包中,Writable可以作为MapReduce支持的类型也是因为实现了这个框架,类不多,我们从几个接口说起。

Serializer

定义了一组接口,打开流,序列化,关闭流
  1. public interface Serializer <T>  {
  2. void open(java.io.OutputStream outputStream) throws java.io.IOException;
  3. void serialize(T t) throws java.io.IOException;
  4. void close() throws java.io.IOException;
  5. }

Deserializer

定义了一组接口,打开流,反序列化,关闭流
  1. public interface Deserializer <T>  {
  2. void open(java.io.InputStream inputStream) throws java.io.IOException;
  3. T deserialize(T t) throws java.io.IOException;
  4. void close() throws java.io.IOException;
  5. }

Serialization

定义了一组接口,判断是否支持输入的类,根据输入的类给出序列化接口和反序列化接口
  1. public interface Serialization <T>  {
  2. boolean accept(java.lang.Class<?> aClass);
  3. org.apache.hadoop.io.serializer.Serializer<T> getSerializer(java.lang.Class<T> tClass);
  4. org.apache.hadoop.io.serializer.Deserializer<T> getDeserializer(java.lang.Class<T> tClass);
  5. }

WritableSerialization

如果你想自己定义一个类似Writable这样的框架,那么你首先需要的就是实现上面三个接口,那么我们先来看下Writable是如何实现的。
  1. <pre style="word-wrap: break-word; white-space: pre-wrap; ">public class WritableSerialization extends Configured
  2. implements Serialization<Writable> {
  3. static class WritableDeserializer extends Configured
  4. implements Deserializer<Writable> {
  5. private Class<?> writableClass;
  6. private DataInputStream dataIn;
  7. public WritableDeserializer(Configuration conf, Class<?> c) {
  8. setConf(conf);
  9. this.writableClass = c;
  10. }
  11. public void open(InputStream in) {
  12. if (in instanceof DataInputStream) {
  13. dataIn = (DataInputStream) in;
  14. } else {
  15. dataIn = new DataInputStream(in);
  16. }
  17. }
  18. public Writable deserialize(Writable w) throws IOException {
  19. Writable writable;
  20. if (w == null) {
  21. writable
  22. = (Writable) ReflectionUtils.newInstance(writableClass, getConf());
  23. } else {
  24. writable = w;
  25. }
  26. writable.readFields(dataIn);
  27. return writable;
  28. }
  29. public void close() throws IOException {
  30. dataIn.close();
  31. }
  32. }
  33. static class WritableSerializer implements Serializer<Writable> {
  34. private DataOutputStream dataOut;
  35. public void open(OutputStream out) {
  36. if (out instanceof DataOutputStream) {
  37. dataOut = (DataOutputStream) out;
  38. } else {
  39. dataOut = new DataOutputStream(out);
  40. }
  41. }
  42. public void serialize(Writable w) throws IOException {
  43. w.write(dataOut);
  44. }
  45. public void close() throws IOException {
  46. dataOut.close();
  47. }
  48. }
  49. public boolean accept(Class<?> c) {
  50. return Writable.class.isAssignableFrom(c);
  51. }
  52. public Deserializer<Writable> getDeserializer(Class<Writable> c) {
  53. return new WritableDeserializer(getConf(), c);
  54. }
  55. public Serializer<Writable> getSerializer(Class<Writable> c) {
  56. return new WritableSerializer();
  57. }
  58. }</pre>

两个内部静态类分别实现Serializer和Deserializer接口,然后getSerializer和getDeserializer分别实例化WritableSerializer和WritableDeserializer,

accept方法仅仅是判断输入类是否是Writable的子类。
通过io.serializations指定已实现Serialization,各个类之间通过逗号隔开,默认的Serialization有WritableSerialization和Avro中Serialization,
这也就是说默认情况下,只有Writable和Avro里的对象可以在MapReduce中使用。
那么你可能有疑问了,hadoop是如何知道一个类该交给哪个Serialization呢,答案也在这个包中,请看

SerializationFactory

先看他的构造器
  1. public SerializationFactory(Configuration conf) {
  2. super(conf);
  3. for (String serializerName : conf.getStrings("io.serializations",
  4. new String[]{"org.apache.hadoop.io.serializer.WritableSerialization"})) {
  5. add(conf, serializerName);
  6. }
  7. }

可知他是从io.serializations属性指定的实现了Serialization的类,然后再看他是如何知道选哪个Serialization的

  1. public <T> Serialization<T> getSerialization(Class<T> c) {
  2. for (Serialization serialization : serializations) {
  3. if (serialization.accept(c)) {
  4. return (Serialization<T>) serialization;
  5. }
  6. }
  7. return null;
  8. }

好吧,就是这么简单,判断一下是否是对应的子类而已。

这个包里还实现了JavaSerialization,其实就是Java对象的序列化,很多人觉得,这个好简单的,我只要实现java中的序列化接口就可以了,
不用那么费事搞什么Writable和Avro,但是,千万别这么想,非常不推荐使用java对象的序列化,并且详尽的解释为什么不推荐:

为什么不使用java序列化

1.java序列化不够灵活,为了更好的控制序列化的整个流程所以使用Writable

2.java序列化不符合序列化的标准,没有做一定的压缩,java序列化首先写类名,然后再是整个类的数据,而且成员对象在序列化中只存引用,成员对象的可以出现的位置很随机,既可以在序列化的对象前,也可以在其后面,这样就对随机访问造成影响,一旦出错,整个后面的序列化就会全部错误,但是
Writable完美的弥补了这一点,因为Writable中每一条纪录间是相互独立的
3.Java序列化每次序列化都要重新创建对象,内存消耗大,而Writable是可以重用的。

序列化IDL

为了和其他语言交互,必须定义序列化的IDL,原先定义的IDL在org.apache.hadoop.record包里,但是后来一直没用起来就淘汰掉了,现在比较常用的就是Avro,后面我们会重点着墨讲解。
Apache的Thrift和Google的Protocol Buffer也是比较流行的序列化框架,但是在Hadoop里使用是有限的,只用于RPC和数据交互,不过有一个开源项目elephant-bird可以把他们使用在MapReduce上。

Mapreduce之序列化框架(转自http://blog.csdn.net/lastsweetop/article/details/9376495)的更多相关文章

  1. 转:Java面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101

    Java面试题集(51-70) Java程序员面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101 摘要:这一部分主要 ...

  2. http://blog.csdn.net/luoshengyang/article/details/6651971

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6651971 在Android系统中,提供了独特 ...

  3. http://blog.csdn.net/v_july_v/article/details/6543438

    本文转载至: http://blog.csdn.net/v_july_v/article/details/6543438 算法 程序员面试.算法研究.编程艺术.红黑树.数据挖掘5大经典原创系列集锦与总 ...

  4. http://blog.csdn.net/baimafujinji/article/details/10931621

    书接上文,本文章是该系列的第二篇,按照总纲中给出的框架,本节介绍三个中值定理,包括它们的证明及几何意义.这三个中值定理是高等数学中非常基础的部分,如果读者对于高数的内容已经非常了解,大可跳过此部分.当 ...

  5. [Android Pro] https://blog.csdn.net/gaugamela/article/details/79143309

    原文地址:https://blog.csdn.net/gaugamela/article/details/79143309 最近遇到这样一个问题: 第三方的SDK除了Jar包外,还提供了对应的so文件 ...

  6. RedHat如何关闭防火墙 : http://blog.csdn.net/chongxin1/article/details/76072758

    版本号:RedHat6.5   JDK1.8   Hadoop2.7.3 hadoop  说明:从版本2开始加入了Yarn这个资源管理器,Yarn并不需要单独安装.只要在机器上安装了JDK就可以直接安 ...

  7. 转-spring-boot 注解配置mybatis+druid(新手上路)-http://blog.csdn.net/sinat_36203615/article/details/53759935

    spring-boot 注解配置mybatis+druid(新手上路) 转载 2016年12月20日 10:17:17 标签: sprinb-boot / mybatis / druid 10475 ...

  8. mybaits入门(含实例教程和源码) http://blog.csdn.net/u013142781/article/details/50388204

    前言:mybatis是一个非常优秀的存储过程和高级映射的优秀持久层框架.大大简化了,数据库操作中的常用操作.下面将介绍mybatis的一些概念和在eclipse上的实际项目搭建使用. 一.mybati ...

  9. http://blog.csdn.net/LANGXINLEN/article/details/50421988

    GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地 ...

随机推荐

  1. Selenium2学习-028-WebUI自动化实战实例-026-获取页面元素值或者元素属性值

    在自动化脚本编写过程中,经常需要获取页面元素的文本进行判断,以便对于不同的文本进行不同的处理.比如:很多的购物网站,加入购物车的按钮是有多个状态的(加入购物车.到货通知.暂不销售等),那么在实际的操作 ...

  2. 针对应用程序池“xxxxxx”的模板永久性缓存初始化失败,解决方法

    日志名称:          Application 来源:            Active Server Pages 日期:            2014-11-22 9:09:39 事件 I ...

  3. ionic 上拉加载更多&瀑布流加载&滚动到底部加载更多 主意事项

    首先下拉刷新的代码是这样的,标红的地方为关键代码 <html> <head> <meta charset="utf-8"> <meta n ...

  4. 给JBoss种蛊分析

    JBoss又发现漏洞了,安全圈儿为之一紧. 知道创宇安全研究团队再次本着科普的情怀收集跟JBoss安全相关的材料,为安全行业再出一把力. 这里先给JBoss正下名.通常所说的JBoss,全称是JBos ...

  5. 淘宝杨志丰:OceanBase--淘宝结构化大数据解决之道

    时至今日,“Big data”(大数据)时代的来临已经毋庸置疑,尤其是在电信.金融等行业,几乎已经到了“数据就是业务本身”的地步.这种趋势已经让很多相信数据之力量的企业做出改变.恰逢此时,为了让更多的 ...

  6. mysql -B 恢复与不加

    -B 跟--database 意义一样 在默认不指定库时候 连续名称,只有第一个名称为库名,后面的都为表名 而使用 -B 或者 --database 之后 所有的名 都是库名 1 导出单个库时候加了- ...

  7. Spring MVC框架下在java代码中访问applicationContext.xml文件中配置的文件(可以用于读取配置文件内容)

    <bean id="propertyConfigurer" class="com.****.framework.core.SpringPropertiesUtil& ...

  8. [ArcEngine]Geotransformation地理变换

    Geotransformation 地理变换 The Abridged Molodensky transformation is a three parameter transformation三参 ...

  9. INSIDE COM 最后一章例子 TANGRAM 编译笔记

    VS2013项目下载地址: http://pan.baidu.com/s/1gemrBrl 注册并运行: 使用管理员权限. 运行 REGISTER.BAT. 然后运行 TANGRAM.EXE 即可. ...

  10. 【转】线程、Thread类和线程终止

    一.线程Thread启动 0. Thread类实现了java.lang.Runnable接口,即实现了run方法.虽然在Sun JDK中,start()调用了start0()方法,start0()方法 ...