当前位置: 首页>>编程语言>>正文


Spark二进制文件读写

qingchuan 编程语言 去评论

在大数据处理中,有时候要将spark集群上处理好的数据拷贝到本地做进一步处理:比如本地单机运算或者作为在线服务的数据。如果直接拷贝字符串文本,耗费带宽和时间。如何来优化这个拷贝性能呢?假设要拷贝的是海量整数数据,比如Int32, 如果我们用字符串传递,可能需要10个Byte;如果使用二进制字节传递,我们只需要4个Byte。

不同的传递方式,有2.5倍的空间节省,在海量数据的情况下,这个优化是非常可观的。那么,问题变成了:如何使用spark将数据存成二进制格式,并且这个二进制在本地是可以解析的呢?

我们知道,目前spark[version<=1.6]可以比较方便地读取二进制文件,使用的接口是:

sc.binaryRecords

但是并没有saveAsBinaryFile之类的方法,只是有

sc.saveAsSequenceFile

之类的方法可以保存二进制文件,但是这个方法保存的结果是sequence格式,在本地不借助第三方库解析起来非常不便。

事实上,通过一些简单继承和重载,我们可以实现自己的saveAsBinaryFile:只需要自己实现一个hadoop文件的OutputFormat。

假设我们现在要保存RDD[(Long, Long)], 以scala语言为例,简要coding说明如下:

首先定义一个自己的hadoop文件输出类BinaryFileOutputFormat[java语言],继承自FileOutputFormat ,参考Spark源码中的TextOutputFormat。

Screen Shot 2016-06-07 at 20.15.09

上面只图示了部分代码,最关键的是:重写writeObject方法,改为将(Long, Long)序列化为java的Byte[]之后再输出,其他变量和方法适当修改。

然后定义一个saveAsBinaryFile[scala语言]方法。

Screen Shot 2016-06-07 at 20.28.38

最后生成的文件可以使用hadoop fs -cat /xxx/* 拷贝到本地,再使用各种语言解析, 例如使用C/C++的fread读取8+8 Bytes,然后反序列化为长整数。

本文由《纯净的天空》出品。文章地址: https://vimsky.com/article/1049.html,未经允许,请勿转载。