SparkStreaming如何解决小文件问题

使用sparkstreaming时,如果实时计算结果要写入到HDFS,那么不可避免的会遇到一个问题,那就是在默认情况下会产生非常多的小文件,这是由sparkstreaming的微批处理模式和DStream(RDD)的分布式(partition)特性导致的,sparkstreaming为每个partition启动一个独立的线程来处理数据,一旦文件输出到HDFS,那么这个文件流就关闭了,再来一个batch的parttition任务,就再使用一个新的文件流,那么假设,一个batch为10s,每个输出的DStream有32个partition,那么一个小时产生的文件数将会达到(3600/10)*32=11520个之多。众多小文件带来的结果是有大量的文件元信息,比如文件的location、文件大小、block number等需要NameNode来维护,NameNode会因此鸭梨山大。不管是什么格式的文件,parquet、text,、JSON或者 Avro,都会遇到这种小文件问题,这里讨论几种处理Sparkstreaming小文件的典型方法。

增加batch大小

这种方法很容易理解,batch越大,从外部接收的event就越多,内存积累的数据也就越多,那么输出的文件数也就回变少,比如上边的时间从10s增加为100s,那么一个小时的文件数量就会减少到1152个。但别高兴太早,实时业务能等那么久吗,本来人家10s看到结果更新一次,现在要等快两分钟,是人都会骂娘。所以这种方法适用的场景是消息实时到达,但不想挤压在一起处理,因为挤压在一起处理的话,批处理任务在干等,这时就可以采用这种方法(是不是很像spark内部的pipeline模式,但是要注意区别哦)。

Coalesce大法好?

文章开头讲了,小文件的基数是:batch_number*partition_number,而第一种方法是减少batch_number,那么这种方法就是减少partition_number了,这个api不细说,就是减少初始的分区个数。看过spark源码的童鞋都知道,对于窄依赖,一个子RDD的partition规则继承父RDD,对于宽依赖(就是那些个叉叉叉ByKey操作),如果没有特殊指定分区个数,也继承自父rdd。那么初始的SourceDstream是几个partiion,最终的输出就是几个partition。所以Coalesce大法的好处就是,可以在最终要输出的时候,来减少一把partition个数。但是这个方法的缺点也很明显,本来是32个线程在写256M数据,现在可能变成了4个线程在写256M数据,而没有写完成这256M数据,这个batch是不算做结束的。那么一个batch的处理时延必定增长,batch挤压会逐渐增大。这种方法也要慎用,切鸡切鸡啊!

SparkStreaming外部来处理

我们既然把数据输出到hdfs,那么说明肯定是要用hive或者sparksql这样的“sql on hadoop”系统类进一步进行数据分析,而这些表一般都是按照半小时或者一小时、一天,这样来分区的(注意不要和sparkStreaming的分区混淆,这里的分区,是用来做分区裁剪优化的),那么我们可以考虑在SparkStreaming外再启动定时的批处理任务来合并SparkStreaming产生的小文件。这种方法不是很直接,但是却比较有用,“性价比”较高,唯一要注意的是,批处理的合并任务在时间切割上要把握好,搞不好就可能回去合并一个还在写入的SparkStreaming小文件。

自己调用foreach去append

SparkStreaming提供的foreach这个outout类api,可以让我们自定义输出计算结果的方法。那么我们其实也可以利用这个特性,那就是每个batch在要写文件时,并不是去生成一个新的文件流,而是把之前的文件打开。考虑这种方法的可行性,首先,HDFS上的文件不支持修改,但是很多都支持追加,那么每个batch的每个partition就对应一个输出文件,每次都去追加这个partition对应的输出文件,这样也可以实现减少文件数量的目的。这种方法要注意的就是不能无限制的追加,当判断一个文件已经达到某一个阈值时,就要产生一个新的文件进行追加了。

上边这些方法我都有尝试过,各有利弊,大家在使用时多加注意就可以了。

更多spark相关交流、分享、讨论,请加入知识星球,BAT一线工程师为你答疑解惑,免费修改简历,并进行面试指导。

原文发布于微信公众号 - Spark学习技巧(bigdatatip)

原文发表时间:2018-06-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏架构师之路

线上服务CPU100%问题快速定位实战

功能问题,通过日志,单步调试相对比较好定位。 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底。 58到家架构部,...

40311
来自专栏QQ空间开发团队的专栏

iOS 高性能图片架构与设计

一个优秀的图片组件应该具有这些特性:集并发控制,请求合并,下载,缓存,缓存自动淘汰,图片处理,动画的从数据源到图片显示的一站式解决方案。做到图片加载展示如丝般顺...

2.3K0
来自专栏pangguoming

JS生成UUID

一、UUID是什么   UUID就是Universal Unique IDentifier的缩写,它是一个128位,16字节的值,并确保在时间和空间上唯一。 它...

3878
来自专栏三木的博客

perf ,比较好的一个程序性能测试工具

面对一个问题程序,最好采用自顶向下的策略。先整体看看该程序运行时各种统计事件的大概,再针对某些方向深入细节。而不要一下子扎进琐碎细节,会一叶障目的。 对于优化自...

2348
来自专栏服务端思维

报表导出

有的时候,我们需要将一部分报表数据以 Excel 文件的形式进行导出,并以离线的方式进行查阅。对于 Excel 报表导出,一种做法是服务端提供 JSON 格式的...

753
来自专栏数据和云

性能优化:Linux环境下合理配置大内存页

熊军(老熊) 云和恩墨西区总经理 Oracle ACED,ACOUG核心会员 PC Server发展到今天,在性能方面有着长足的进步。64位的CPU在数年前都已...

3885
来自专栏社区的朋友们

基于 SPP 模块的优化实践

SPP 框架的微线程模式在网络密集型 Server 开发中优势明显,在使用过程中,也遇到过一些性能问题,下面跟大家分享下解决思路。

6290
来自专栏owent

协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比

libcopp很早就实现完成了v2版本,现在迁移进atsf4g-co/tree/sample_solution以后也把v2分支正式并入了主干。原来的版本切出到v...

462
来自专栏纯洁的微笑

一次线上问题排查所引发的思考

之前或多或少分享过一些内存模型、对象创建之类的内容,其实大部分人看完都是懵懵懂懂,也不知道这些的实际意义。

881
来自专栏Java面试笔试题

在进行数据库编程时,连接池有什么作用?

由于创建连接和释放连接都有很大的开销(尤其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,释放连接需要进行TCP四次握手,造成的开销是不可忽视...

1122

扫码关注云+社区