spark中saveAsTextFile如何最终生成一个文件

项目场景:

  • 一般而言,saveAsTextFile会按照执行task的多少生成多少个文件,比如part-00000一直到part-0000n,n自然就是task的个数,亦即是最后的stage的分区数。那么有没有办法最后只生成一个文件,而不是成百上千个文件了?答案自然是有办法。

误区

  • 在RDD上调用 coalesce(1,true).saveAsTextFile(), 意味着做完计算之后将数据汇集到一个分区,然后再执行保存的动作,显然,一个分区,Spark自然只起一个task来执行保存的动作,也就只有一个文件产生了。又或者,可以调用repartition(1),它其实是coalesce的一个包装,默认第二个参数为true。

  • 事情最终就这么简单吗?
      显然不是。你虽然可以这么做,但代价是巨大的。因为Spark面对的是大量的数据,并且是并行执行的,如果强行要求最后只有一个分区,必然导致大量的磁盘IO和网络IO产生,并且最终执行reduce操作的节点的内存也会承受很大考验。Spark程序会很慢,甚至死掉。

  • 这往往是初学Spark的一个思维陷阱,需要改变原先那种单线程单节点的思维,对程序的理解要转变多多个节点多个进程中去,需要熟悉多节点集群自然产生多个文件这种模式。

  • 此外,saveAsTextFile要求保存的目录之前是没有的,否则会报错。所以,最好程序中保存前先判断一下目录是否存在。

  • 当我运行完一个Spark程序想把结果保存为saveAsTextFile,
    结果使用Hadoop fs -ls /output 后发现里面有一系列的part,好几千个。

  • 原因
    运行Spark的时候把数据分成了很多份(partition),每个partition都把自己的数据保存成partxxx文件形式。
    如果想保存为一份的话,就要:
    collect
    或者
    data.coalesce(1,true).saveAsTextFile()
    也或者

data.repartition(1).saveAsTextFile( )       //You can also use repartition(1), which is just a wrapper for coalesce() with the suffle argument set to true.

data.repartition(1).saveAsTextFile( “HDFS://OUTPUT”)
  • 问题:
    但是如果你的数据很大,难以在单机内存上装下,以上操作可能会造成单机内存不足(OOM)
    原因在于以上操作都是讲分布在各个机器上的数据汇总到单机,然后再保存到磁盘(HDFS)上。
    以上操作将各个机器上的RDD partition 合并到单一主机后再读入磁盘。

解决方案:

以下给出更安全的操作,即采用HDFS磁盘合并操作。

如果已经存了很多个part:
可以把大文件夹getmerge:

把HDFS 上的多个文件 合并成一个 本地文件:

hadoop fs -getmerge /hdfs/output   /local/file.txt

也可以:

hadoop    fs   -cat    /hdfs/output/part-r-* >   /local/file.txt
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值