针对小文件的spark wholeTextFiles()
场景:推送过来的数据文件数量很多,并且每个只有10-30M的大小
spark读取hdfs一般都是用textfile(),但是对于这种情况,如果使用textFile默认产生的分区数将与文件数目一致,产生大量的任务。
对应这种小文件,spark提供了一个特殊的api, wholeTextFiles(), wholeTextFiles主要用于处理大量的小文件,源码如下:
/**
* Read a directory of text files from HDFS, a local file system (available on all nodes), or any
* Hadoop-supported file system URI. Each file is read as a single record and returned in a
* key-value pair, where the key is the path of each file, the value is the content of each file.
*
* <p> For example, if you have the following files:
* {{{
* hdfs://a-hdfs-path/part-00000
* hdfs://a-hdfs-path/part-00001
* ...
* hdfs://a-hdfs-path/part-nnnnn
* }}}
*
* Do `val rdd = sparkContext.wholeTextFile("hdfs://a-hdfs-path")`,
*
* <p> then `rdd` contains
* {{{
* (a-hdfs-path/part-00000, its content)
* (a-hdfs-path/part-00001, its content)
* ...
* (a-hdfs-path/part-nnnnn, its content)
* }}}
*
* @note Small files are preferred, large file is also allowable, but may cause bad performance.
* @note On some filesystems, `.../path/*` can be a more efficient way to read all files
* in a directory rather than `.../path/` or `.../path`
* @note Partitioning is determined by data locality. This may result in too few partitions
* by default.
*
* @param path Directory to the input data files, the path can be comma separated paths as the
* list of inputs.
* @param minPartitions A suggestion value of the minimal splitting number for input data.
* @return RDD representing tuples of file path and the corresponding file content
*/
def wholeTextFiles(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[(String, String)] = withScope {
assertNotStopped()
val job = NewHadoopJob.getInstance(hadoopConfiguration)
// Use setInputPaths so that wholeTextFiles aligns with hadoopFile/textFile in taking
// comma separated files as input. (see SPARK-7155)
NewFileInputFormat.setInputPaths(job, path)
val updateConf = job.getConfiguration
new WholeTextFileRDD(
this,
classOf[WholeTextFileInputFormat],
classOf[Text],
classOf[Text],
updateConf,
minPartitions).map(record => (record._1.toString, record._2.toString)).setName(path)
}
wholeTextFiles读取文件,输入参数为路径,并且可以设置为多个路径,多个路径之间以逗号分隔。wholeTextFiles读取数据会生成一个Tuple2,Tuple2的第一个元素是该文件的完整路径名,第二个元素表示该文件的文本内容(context)。比如两行数据:
jack,1011,shanghai
kevin,2022,beijing
返回的文本内容是一行字符串,源数据的每行数据以换行符\n分隔,也即:jack,1011,shanghai\nkevin,2022,beijing
分区数可以自定义,如果不显示指定,则默认分区数定义如下:
def defaultMinPartitions: Int = math.min(defaultParallelism, 2)
也就是在不指定分区的情况下,大部分情况都是以2个分区来处理数据。
样例代码:
处理逻辑可以理解为每个小文件对应一个城市的某个区下的所有道路相关的数据(当然了实际数据并不是,哪个城市有几万个几十万个区)。文件名为区的名字,文件内容为道路的名称以及相关数据,在每行道路数据上加上区的名字。
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.util.SizeEstimator;
import scala.Tuple2; public class TestWholeTextFiles { public static void main(String[] args) {
SparkConf conf = new SparkConf();
SparkSession spark = SparkSession
.builder()
.appName("TestWholeTextFiles")
.master("local")
.config(conf)
.enableHiveSupport()
.getOrCreate();
JavaSparkContext sc = JavaSparkContext.fromSparkContext(spark.sparkContext());
JavaPairRDD<String, String> javaPairRDD =
sc.wholeTextFiles("hdfs://master01.xx.xx.cn:8020/kong/capacityLusunData_bak"); System.out.println("javaPairRDD分区数:"+javaPairRDD.getNumPartitions());//
JavaRDD<String> map = javaPairRDD.map((Function<Tuple2<String, String>, String>) v1 -> {
int index = v1._1.lastIndexOf("/");
String road_id = v1._1.substring(index+1).split("\\.")[0];
return v1._2.replace("\n", "\\|"+road_id + "\n");
});
System.out.println("mapRDD分区数:"+map.getNumPartitions());//
map.saveAsTextFile("hdfs://master01.xx.xx.cn:8020/kong/data/testwholetextfiles/out");
}
}
1
针对小文件的spark wholeTextFiles()的更多相关文章
- Spark使用CombineTextInputFormat缓解小文件过多导致Task数目过多的问题
目前平台使用Kafka + Flume的方式进行实时数据接入,Kafka中的数据由业务方负责写入,这些数据一部分由Spark Streaming进行流式计算:另一部分数据则经由Flume存储至HDFS ...
- Hadoop对小文件的解决方式
小文件指的是那些size比HDFS的block size(默认64M)小的多的文件.不论什么一个文件,文件夹和block,在HDFS中都会被表示为一个object存储在namenode的内存中, 每一 ...
- Hadoop小文件存储方案
原文地址:https://www.cnblogs.com/ballwql/p/8944025.html HDFS总体架构 在介绍文件存储方案之前,我觉得有必要先介绍下关于HDFS存储架构方面的一些知识 ...
- 如何利用Hadoop存储小文件
**************************************************************************************************** ...
- spark sql/hive小文件问题
针对hive on mapreduce 1:我们可以通过一些配置项来使Hive在执行结束后对结果文件进行合并: 参数详细内容可参考官网:https://cwiki.apache.org/conflue ...
- Spark SQL 小文件问题处理
在生产中,无论是通过SQL语句或者Scala/Java等代码的方式使用Spark SQL处理数据,在Spark SQL写数据时,往往会遇到生成的小文件过多的问题,而管理这些大量的小文件,是一件非常头疼 ...
- Spark:spark df插入hive表后小文件数量多,如何合并?
在做spark开发过程中,时不时的就有可能遇到租户的hive库目录下的文件个数超出了最大限制问题. 一般情况下通过hive的参数设置: val conf = new SparkConf().setAp ...
- 数据算法 --hadoop/spark数据处理技巧 --(17.小文件问题 18.MapReuce的大容量缓存)
十七.小文件问题 十八.MR的大容量缓存 在MR中使用和读取大容量缓存,(也就是说,可能包括数十亿键值对,而无法放在一个商用服务器的内存中).本次提出的算法通用,可以在任何MR范式中使用.(eg:MR ...
- Spark优化之小文件是否需要合并?
我们知道,大部分Spark计算都是在内存中完成的,所以Spark的瓶颈一般来自于集群(standalone, yarn, mesos, k8s)的资源紧张,CPU,网络带宽,内存.Spark的性能,想 ...
随机推荐
- 转入软工后第一节java课的作业
这个作业,鸽了好久.本来大家都在中秋前发了,我摸摸索索加上各种缓慢的学习,终于是将他做完了. 做完之后,java最基本的输入输出功能都基本学习到了.下面附上代码: import java.util.* ...
- leetcode 0218
目录 ✅ 1200. 最小绝对差 描述 解答 cpp py ✅ 897. 递增顺序查找树 描述 解答 cpp 指针问题? fuck ptr py ✅ 183. 从不订购的客户 描述 解答 sql to ...
- OS(操作系统)结构
1.整体式: 模块设计(独立的) 调用自由 用全局变量来通信 缺点:信息不安全,维护更新比较难 2.层次结构(典型的如TCP/IP协议): 所有的模块排成若干层,相邻的互相依赖调用 按调用次序来安排 ...
- PAT T1003 Universal Travel Sites
网络流模板~ #include<bits/stdc++.h> using namespace std; ; const int inf=1e9; queue<int> q; i ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定文本右对齐
<!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...
- 1007 Maximum Subsequence Sum (25分) 求最大连续区间和
1007 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1, N2, ..., NK }. A ...
- [理解] Linux 作为一个服务器是怎样的存在 (一)
长期以来我就一直有一个疑问, 为什么当我们选择使用服务器的时候都会选择 Linux 作为操作系统, 以至于只要说到服务器就会不由自主的想到Linux, 那么Linux到底是什么呢? 当然我也不会妄谈天 ...
- 32 commons-lang包学习
maven依赖 <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lan ...
- js中数值各进制之间的转换
十进制转换为二进制 toString()方法可把一个 Number 对象转换为一个字符串,并返回结果.语法如下: NumberObject.toString(radix); 其中,radix为可选.规 ...
- error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 解决方法
在VS2012中生成时出错:error C4430: missing type specifier - int assumed. Note: C++ does not support default- ...