Apache spark Spark分区(ing)如何处理HDFS中的文件?
我正在使用HDFS在集群上与ApacheSpark合作。据我所知,HDFS正在数据节点上分发文件。因此,如果一个服务器在文件系统上放置一个“file.txt”,它将被分割成多个分区。 现在我打电话来Apache spark Spark分区(ing)如何处理HDFS中的文件?,apache-spark,hdfs,Apache Spark,Hdfs,我正在使用HDFS在集群上与ApacheSpark合作。据我所知,HDFS正在数据节点上分发文件。因此,如果一个服务器在文件系统上放置一个“file.txt”,它将被分割成多个分区。 现在我打电话来 rdd = SparkContext().textFile("hdfs://.../file.txt") 来自Apache Spark。 rdd现在是否自动在文件系统上使用与“file.txt”相同的分区? 我打电话时会发生什么 rdd.repartition(x) 其中x>然后是hdfs使用
rdd = SparkContext().textFile("hdfs://.../file.txt")
来自Apache Spark。
rdd现在是否自动在文件系统上使用与“file.txt”相同的分区?
我打电话时会发生什么
rdd.repartition(x)
其中x>然后是hdfs使用的分区?Spark是否会重新安排hdfs上的数据以在本地工作
例如:
我在HDFS系统上放了一个30GB的文本文件,该文件分布在10个节点上。
将点燃
a) 使用相同的10个partitons?b)当我调用重分区(1000)时,在集群中随机移动30GB?当Spark从HDFS读取文件时,它会为单个输入拆分创建单个分区。输入拆分由用于读取此文件的Hadoop
InputFormat
设置。例如,如果您在Hadoop中使用textFile()
它将是TextInputFormat
,它将为单个HDF块返回单个分区(但是分区之间的拆分将在行拆分中完成,而不是精确的块拆分),除非您有一个压缩文本文件。在压缩文件的情况下,您将获得单个文件的单个分区(因为压缩文本文件不可拆分)
当您调用rdd.repartition(x)
时,它将执行从rdd
中的N
分区到您想要的x
分区的数据洗牌,分区将在循环的基础上完成
如果您有一个30GB的未压缩文本文件存储在HDFS上,那么使用默认的HDFS块大小设置(128MB),它将存储在235个块中,这意味着您从该文件读取的RDD将有235个分区。当您调用
重新分区(1000)
时,您的RDD将被标记为要重新分区,但事实上,只有当您在这个RDD(延迟执行概念)之上执行一个操作时,它才会被洗牌到1000个分区。如果@0x0FFF从HDFS中获取作为输入文件,那么它的计算结果与此类似RDD=SparkContext().textFile(“hdfs://.../file.txt”
并且当您执行rdd.getNumpations
时,它将产生Max(2,HDFS块数)
。我做了很多实验,结果发现了这一点。同样,您可以显式地执行rdd=SparkContext().textFile(“hdfs://.../file.txt“,400)
将400作为分区,甚至可以通过rdd重新分区。重新分区
或通过rdd减少到10。合并(10)
下面是“HDFS中的块如何作为分区加载到Spark Worker中的快照”
在此图像中,4个HDFS块作为Spark分区加载到3个Worker内存中
示例:我在HDFS系统上放置了一个30GB的文本文件,该文件分布在10个节点上 将点燃 a)使用相同的10个分区? Spark将与分区相同的10个HDFS块加载到workers内存中。我假设30GB文件的块大小应该是3GB,以获得10个分区/块(默认配置) b)当我调用重新分区(1000)时,在集群中随机移动30GB? 是,Spark在工作节点之间洗牌数据,以便在工作节点内存中创建1000个分区 注:
使用spark sql读取非带扣HDFS文件(如拼花地板)时,数据帧分区的数量取决于以下因素:
(大致翻译为应用程序可用的#内核)spark.default.parallelism
(默认128MB)spark.sql.files.maxPartitionBytes
(默认4MB)spark.sql.files.openCostInBytes
- 如果您有足够的内核并行读取所有数据(即每128MB数据至少有一个内核)
AveragePartitionSize≈ 最小值(4MB,TotalDataSize/#核心) 分区数≈ TotalDataSize/AveragePartitionSize
- 如果你没有足够的内核
AveragePartitionSize≈ 128MB 分区数≈ TotalDataSize/AveragePartitionSize
精确的计算有点复杂,可以在FileSourceScanExec的代码库中找到,请参阅。那么,我从中得出的
rdd=SparkContext().textFile(“hdfs://.../file.txt“”
将导致RDD被划分为与文件存储在HDFS中相同数量的块?只有在修复rdd的情况下,才能将其放入更多的分区。重新分区(x)?不完全是这样。理想情况下,您将获得与HDFS中相同数量的块。但如果文件中的行太长(比块大小长),分区的数量就会减少。在这种情况下,更改分区数的首选方法是直接将其传递给调用rdd=SparkContext().textFile(“hdfs://.../file.txt“,400)
,其中400是分区数。这种情况下,400次分割的分区将由Hadoop TextInputFormat完成,而不是Spark,而且工作速度要快得多。Sparkrepartition()
会在整个集群中洗牌数据,而不是真正有效地感谢您的精彩问答!你能解释一下“用Hadoop TextInputFormat进行400次分区”的情况吗?0x0FFF:如果输入文件是SequenceFile[BytesWritable,BytesWritable],那么我必须使用Hadoop文件或SequenceFile(不能使用textFile)。问题是BytesWritable不可序列化,因此我将其转换为字节数组(byte[]),但它返回一个错误“默认分区器无法对数组键进行分区”。我已经看过代码了,Spark不支持数组键。那么你有什么解决办法吗?第一个问题:只要阅读TextInputF的代码就可以了
HDFS Block -> Spark partition : One block can represent as One partition (by default)
Spark partition -> Workers : Many/One partitions can present in One workers