Spark 从HDFS读取时,通常按文件块(block)数量决定初始partition数,这是怎么实现的?

在 Spark 中,从 HDFS 读取数据时按文件块(block)数量决定初始 partition 数 ,这一机制是通过 Hadoop InputFormat 的分片(split)策略实现的。具体流程如下:


1. HDFS 文件块(Block)与 Spark Partition 的对应关系

  • HDFS 默认块大小(如 128MB/256MB)决定了文件的物理存储分布。

  • Spark 在读取 HDFS 文件时 ,会调用 Hadoop 的 InputFormat(如 TextInputFormatSequenceFileInputFormat)来生成数据分片(InputSplit)。

  • 每个 InputSplit 会映射为一个 Spark Partition ,因此:
    初始 Partition 数 ≈ HDFS 文件块数

    (假设文件未被压缩且未手动指定分区数)。


2. 底层实现机制

(1) 调用 Hadoop API

Spark 通过 HadoopRDDNewHadoopRDD 读取 HDFS 数据时,会使用 Hadoop 的 InputFormat.getSplits() 方法生成分片。

  • 关键类

    • org.apache.hadoop.mapreduce.InputFormat

    • org.apache.spark.rdd.HadoopRDD

(2) 分片(Split)生成逻辑

TextInputFormat 为例:

  1. 按文件块切分

    • 每个 HDFS 文件块(block)默认生成一个 FileSplit(即一个 InputSplit)。

    • 例如:一个 1GB 的文件(128MB/block)会生成 8 个 FileSplit → 对应 8 个 Spark Partition

  2. 处理跨行问题

    • 如果某一行数据跨越两个 block,Hadoop 会通过 网络读取下一个 block 的开头部分,确保数据完整性。
(3) Spark 的 Partition 分配
  • 生成的 InputSplit 会被封装为 HadoopPartition,最终构成 RDD 的分区:

    Scala 复制代码
    // HadoopRDD 中的分区生成逻辑
    override def getPartitions: Array[Partition] = {
      val inputSplits = inputFormat.getSplits(jobConf, minPartitions)
      inputSplits.map(split => new HadoopPartition(id, split.index, split))
    }
    • 这里的 minPartitions 是用户指定的最小分区数(默认不指定时等于 inputSplits.size)。

3. 特殊情况处理

(1) 压缩文件
  • 如果文件是 不可分割的压缩格式 (如 GZIP),整个文件会被视为 一个 InputSplit → 仅生成 1 个 Partition

  • 可分割压缩格式(如 BZip2)仍按 block 切分。

(2) 手动指定分区数
  • 通过 sc.textFile(path, minPartitions) 指定最小分区数时:

    • Spark 会尝试合并或拆分 InputSplit 以满足 minPartitions 要求。

    • 但最终分区数可能 大于 minPartitions(因为不能拆分单个 block)。

(3) 小文件合并
  • 大量小文件会导致 Partition 数过多(每个小文件至少 1 个 Partition),可通过以下方式优化:

    • 使用 coalesce 减少分区。

    • 读取时指定 minPartitions(如 sc.textFile("hdfs://path/*.txt", 100))。


4. 验证方法

(1) 查看 RDD 的分区数
Scala 复制代码
val rdd = sc.textFile("hdfs://path/file.txt")
println(rdd.partitions.size)  // 输出实际分区数
(2) 调试 Hadoop InputSplits
Scala 复制代码
val hadoopConf = sc.hadoopConfiguration
val path = new org.apache.hadoop.fs.Path("hdfs://path/file.txt")
val inputFormat = new org.apache.hadoop.mapreduce.lib.input.TextInputFormat
val splits = inputFormat.getSplits(new org.apache.hadoop.mapreduce.JobContext(hadoopConf, null))
println(splits.size)  // 输出Hadoop生成的InputSplit数

5. 总结

关键点 说明
默认规则 1 个 HDFS block → 1 个 InputSplit → 1 个 Spark Partition
压缩文件 不可分割压缩格式(如 GZIP)→ 仅 1 个 Partition
手动控制 sc.textFile(path, minPartitions) 可调整分区数下限
优化建议 避免大量小文件,合理设置 minPartitions

通过这一机制,Spark 天然适配 HDFS 的分布式存储特性,实现数据本地化(Data Locality),减少网络传输开销。

相关推荐
盟接之桥17 小时前
盟接之桥说制造:“盟接之桥”为何成了“断桥”?——制造企业困局突围的三重思考
大数据·人工智能·物联网·产品运营·制造
五度易链-区域产业数字化管理平台17 小时前
如何构建高质量产业数据信息库?五度易链的“八大核心库”与数据治理实践
大数据·人工智能
Elastic 中国社区官方博客17 小时前
用 Elasticsearch 构建一个 ChatGPT connector 来查询 GitHub issues
大数据·人工智能·elasticsearch·搜索引擎·chatgpt·github·全文检索
哲霖软件17 小时前
设备自动化行业ERP选型
大数据
武子康17 小时前
大数据-172 Elasticsearch 索引操作与 IK 分词器落地实战:7.3/8.15 全流程速查
大数据·后端·elasticsearch
学术小白人18 小时前
【落幕通知】2025年能源互联网与电气工程国际学术会议(EIEE 2025)在大连圆满闭幕
大数据·人工智能·机器人·能源·信号处理·rdlink研发家
物流可信数据空间18 小时前
专家解读 | 提升数据流通安全治理能力 促进数据流通开发利用【可信数据空间】
大数据·人工智能·安全
Acrelhuang18 小时前
直击新能源电能质量痛点:安科瑞 APView500 在线监测装置应用方案
大数据·运维·开发语言·人工智能·物联网
龙亘川18 小时前
2025 年中国养老机器人行业全景分析:技术演进、市场格局与商业化路径
大数据·人工智能·机器人
Elastic 中国社区官方博客19 小时前
Elasticsearch:在隔离环境中安装 ELSER 模型
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索