Spark目前支持三种开发语言:Scala、Java、Python,目前我们大量使用Python来开发Spark App(Spark 1.2开始支持使用Python开发Spark Streaming App,我们也准备尝试使用Python开发Spark Streaming App),在这期间关于数据类型的问题曾经困扰我们很长时间,故在此记录一下心路历程。
 
Spark是使用Scala语言开发的,Hadoop是使用Java语言开发的,Spark兼容Hadoop Writable,而我们使用Python语言开发Spark (Streaming) App,Spark Programming Guides(Spark 1.5.1)其中有一段文字说明了它们相互之间数据类型转换的关系:
 
 
也说是说,我们需要处理两个方向的转换:
 
(1)Writable => Java Type => Python Type;
(2)Python Type => Java Type => Writable;
 
其中Java Type与Python Type之间数据类型的转换依赖开源组件Pyrolite,相应的数据类型转换如下:
 
(1)Python Type => Java Type;
 
 
(2)Java Type => Python Type;
 
 
也就是说,Pyrolite已经为Java Type与Python Type之间的数据类型转换建立了“标准”,我们仅仅需要处理Writable与Java Type之间的数据转换就可以了。
 
从上图“Writable Support”中可以看出PySpark已经为我们解决了常用的数据类型转换问题,但可以理解为“基本”数据类型,遇到复杂的情况,还是需要我们特殊处理,PySpark已经为我们考虑到了这种业务场景,为我们提供接口Converter(org.apache.spark.api.python.Converter),使得我们可以根据自己的需要扩展数据类型转换机制:
 
 
接口Converter仅仅只有一个方法convert,其中T表示源数据类型,U表示目标数据类型,参数obj表示源数据值,返回值表示目标数据值。
 
Spark Programming Guides(Spark 1.5.1)也为我们举例说明了一个需要自定义Converter的场景:
 
 
ArrayWritable是Hadoop Writable的一种,因为Array涉及到元素数据类型的问题,因此使用时需要实现相应的子类,如元素数据类型为整型:
 
 
从上面的描述可知,PySpark使用ArrayWritable时涉及到如下两个方向的数据类型转换:
 
(1)Tuple => Object[] => ArrayWritable;
(2)ArrayWritable => Object[] => Tuple;
 
我们以IntArrayWritable为例说明如何自定义扩展Converter,同理也需要处理两个方向的数据类型转换:Tuple => Object[] => ArrayWritable、ArrayWritable => Object[] => Tuple。
 
(1)Tuple => Object[] => IntArrayWritable;
 
假设我们有一个list,list的元素类型为tuple,而tuple的元素类型为int,我们需要将这个list中的所有数据以SequenceFile的形式保存至HDFS。对于list中的每一个元素tuple,Pyrolite可以帮助我们完成Tuple => Object[]的转换,而Object[] => IntArrayWritable则需要我们自定义Converter实现。
 
 
PySpark中使用这个Converter写入数据:
 
 
注意:SequenceFile的数据结构为<key, value>,为了简单起见,key指定为com.sina.dip.spark.converter.IntArrayWritable,value指定为org.apache.hadoop.io.NullWritable(即空值)。
 
运行上述程序时,因为有使用到我们自定义的类,因此需要将com.sina.dip.spark.converter.IntArrayWritable、com.sina.dip.spark.converter.ObjectArrayToIntArrayWritableConverter编译打包为独立的Jar:converter.jar,并通过参数指定,如下:
 
/usr/lib/spark-1.5.1-bin-2.5.0-cdh5.3.2/bin/spark-submit --jars converter.jar 1.5.1/examples/app/spark_app_save_data_to_seqfile.py
 
(2)IntArrayWritable => Object[] => Tuple;
 
我们需要将(1)中写入SequenceFile的Key(IntArrayWritable)还原为list,其中list的元素类型为tuple,tuple的元素类型为int,IntArrayWritable => Object[]也需要用到我们自定义的Converter(Object[] => Tuple由Pyrolite负责):
 
 
PySpark使用这个Converter读取数据:
 
 
同(1),我们需要将com.sina.dip.spark.converter.IntArrayWritable、com.sina.dip.spark.converter.IntArrayWritableToObjectArrayConverter编译打包为独立的Jar:converter.jar,并通过参数指定,如下:
 
/usr/lib/spark-1.5.1-bin-2.5.0-cdh5.3.2/bin/spark-submit --jars converter.jar 1.5.1/examples/app/spark_app_read_data_from_seqfile.py
 
输出结果:
 
 
可以看出,通过自定义扩展的Converter:com.sina.dip.spark.converter.ObjectArrayToIntArrayWritableConverter、com.sina.dip.spark.converter.IntArrayWritableToObjectArrayConverter,我们实现了IntArrayWritable(com.sina.dip.spark.converter.IntArrayWritable)与Tuple(Python)之间的转换。
 
 

Spark PySpark数据类型的转换原理—Writable Converter的更多相关文章

  1. 开发板A/D转换原理

    A/D转换器(Analog-to-Digital Converter)又叫模/数转换器,即使将模拟信(电压或是电流的形式)转换成数字信号.这种数字信号可让仪表,计算机外设接口或是微处理机来加以操作或是 ...

  2. adc转换原理

    模数转换器即A/D转换器,或简称ADC,通常是指一个将模拟信号转变为数字信号的电子元件.通常的模数转换器是将一个输入电压信号转换为一个输出的数字信号.由于数字信号本身不具有实际意义,仅仅表示一个相对大 ...

  3. java学习笔记(3)数据类型、源码、反码、补码、精度损失、基本数据类型互相转换

    关于java中的数据类型: 1.数据类型的作用是什么? 程序当中有很多数据,每一个数据都是有相关类型的,不同数据类型的数据占用的空间大小不同. 数据类型的作用是指导java虚拟机(JVM)在运行程序的 ...

  4. java中数据类型的转换

    数据类型的转换,分为自动转换和强制转换. 自动转换是程序执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换 强制转换必须在代码中声明,转换顺序不受限制 自动数据类 ...

  5. Java的基本数据类型与转换

    1.1 Java为什么需要保留基本数据类型 http://www.importnew.com/11915.html 基本数据类型对大多数业务相关或网络应用程序没有太大的用处,这些应用一般是采用客户端/ ...

  6. java的数据类型的转换

    一:java的数据类型转换除布尔类型boolean(不能转换)有两种:<一> 自动转换: <二> 强制转换 <一>.自动转换:就是将小的数据类型自动转换成大的数据类 ...

  7. JavaScript学习笔记——数据类型强制转换和隐式转换

    javascript数据类型强制转换 一.转换为数值类型 Number(参数) 把任何的类型转换为数值类型 A.如果是布尔值,false为0,true为1 B.如果是数字,转换成为本身.将无意义的后导 ...

  8. eclipse 提交作业到JobTracker Hadoop的数据类型要求必须实现Writable接口

    问:在eclipse中的写的代码如何提交作业到JobTracker中的哪?答:(1)在eclipse中调用的job.waitForCompletion(true)实际上执行如下方法 connect() ...

  9. JAVA数据类型自动转换,与强制转换

    一.数据类型自动转换 public class Test{ public static void main(String[] args){ int a = 1; double b = 1.5; dou ...

随机推荐

  1. Weex命令

    1.下载安装 $ git clone https://github.com/alibaba/weex.git //通过brew安装node $ brew install node //通过node安装 ...

  2. java问题:类的定义,对象的定义?

    java问题:类的定义,对象的定义? 类是一组数据和函数的集合,只是抽象的概念,它的作用就是生成对象,它生成对象后,就为这个对象分了一块存储区,类可以生成无限多个对象,每个对象都有自己的存储区,在类里 ...

  3. BUG Error:Execution failed for task ':app:dexDebug'.

    Error:Execution failed for task ':app:dexDebug'. > com.android.ide.common.process.ProcessExceptio ...

  4. org.hibernate.HibernateException: No CurrentSessionContext configured!

    hibernate可以通过两种方式获得Session: getCurrentSession() 和openSession(). 当通过getCurrentSession()方法时,需要在 hibern ...

  5. .NET性能优化方面的总结

    从2004年底开始接触C#到现在也有2年多的时间了,因为有C++方面的基础,对于C#,我习惯于与C++对比.现在总结一些.NET方面的性能优化方面的经验,算是对这两年多的.NET工作经历的总结.    ...

  6. 淘宝链接中的spm参数

    什么是SPM SPM是淘宝社区电商业务(xTao)为外部合作伙伴(外站)提供的一套跟踪引导成交效果数据的解决方案. 下面是一个跟踪点击到宝贝详情页的引导成交效果数据的SPM示例: http://det ...

  7. CSS jQuery HTML5 CSS3

    jquery css3图片文字介绍鼠标滚动页面动画单页 http://www.17sucai.com/preview/1/2013-12-30/%E5%8A%A8%E7%94%BB%E5%8D%95% ...

  8. iOS与服务器端 GZip压缩问题

    昨天搞了一天的GZip压缩,试了三种方式(libz库,ZipArchive,ASIHttpRequest),一开始都不成功.理论上三个应该都能用的,但我都不行.等我试到第三种方式的时候才知道,不是我的 ...

  9. XMPPFramework ios 例子中链接服务器失败,opnefire 服务器链接失败

    首先说下上周又做了几天得无用功, 之前一直用的是ejabberd ,这次换了opnefire,有人说opnefire跟新的xmpp协议不兼容,后来又更换成了ejabberd, Github 上得dem ...

  10. struts2 测试错题解析

    解析:$.parseJSON()方法是将字符串转换成Json类型数据,$.getJSON()方法是获取JSON数据,两者不用联合使用. 解析: A:ActionContext接口没有getReques ...