DAG 执行框架优于 MapReduce 的地方在哪里?
Created|Updated|系统架构
|Word Count:210|Reading Time:1mins|Post Views:
有个同学问我什么是 DAG 框架。我感觉隐隐约约听过,但又讲不清楚它的概念。
上网搜了一下,我们常见的新大数据执行框架如 Spark、Storm,还有一个我没听过的 Tez,都算 DAG 任务执行框架。他们的主要优点是,可以用 DAG 事先通晓整个任务的全部步骤,然后进行转换优化。如 Tez 就可以把多个任务转换为一个大任务,而 Spark 则可以把相关联的 Map 直接串联起来, 免得多次写回 hdfs(看来 hdfs 也很慢)。传统的 MapReduce 框架为什么不能理解这种优化空间的存在,在任务运行的时候好像一个盲人一样,是个很有意思的话题。
Quora 上的一个相关的问答。
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles
2026-07-13
Spark SQL 与 Catalyst:从 SQL 文本到物理算子树
上一篇解决了 Spark 的容错机制。这一篇进入 SQL 引擎的核心——Catalyst 优化器。 Spark SQL 不只是"在 Spark 上跑 SQL"。它是一个完整的查询编译器,把 SQL 文本或 DataFrame API 调用翻译成优化后的物理执行计划。这个翻译过程由 Catalyst 优化器驱动,经过四个阶段:解析、分析、优化、物理计划生成。 本文只抓一个问题:一条 SQL 从文本到可执行的物理算子树,中间经历了什么变换。 下图展示了 Catalyst 四阶段流水线和一条 SQL 在各阶段的变换过程: 四阶段流水线 12345678910111213141516171819202122232425SQL 文本 / DataFrame API │ ▼┌─────────────────┐│ ① Parsing │ SQL 文本 → Unresolved Logical Plan│ (ANTLR 解析器) │ 列名和表名尚未绑定到实际 schema└────────┬────────┘ │ ...
2025-07-29
经典面试问题的大数据解法——Spark 与 Flink 实战
“100 亿个数中找出最大的 1000 个”、“两个 10GB 的文件找出共同的 URL”——这些经典面试题的本质都是内存放不下。单机方案围绕分治展开,分布式方案则把分治思想映射到集群节点上。本文按问题类型组织,每类问题给出从单机到 Spark/Flink 的渐进式解法,并附上概率数据结构(布隆过滤器、HyperLogLog、Count-Min Sketch)在近似场景中的应用。 引言:大数据问题的共同特征 为什么"内存放不下" 面试中给出的数据规模往往是精心设计的——刚好跨过单机内存的边界: 数据规模 内存需求 典型服务器内存 能否放入内存 1 亿个 int 400 MB 16 GB ✅ 10 亿个 int 4 GB 16 GB ✅(但留给程序的余量不多) 100 亿个 int 40 GB 16 GB ❌ 10 亿个 URL(平均 100 字节) 100 GB 16 GB ❌ 上表只计算了裸数据大小。实际使用 HashMap、HashSet 等容器时,对象头、指针、负载因子会使内存占用膨胀 3-5 倍。 通用解题框架 123...
2026-07-13
内存管理与 Tungsten:堆外内存、序列化与代码生成
上一篇解决了 Shuffle 的物理机制。这一篇进入内存管理——Spark 如何突破 JVM 的内存瓶颈。 Spark 是一个 JVM 应用,天然受制于 Java 的内存模型:对象头开销大、GC 停顿不可控、序列化效率低。Project Tungsten 是 Spark 为解决这三个问题发起的底层优化计划,它从三条线同时推进——堆外内存管理、二进制数据格式、全阶段代码生成。 本文只抓一个问题:Tungsten 的三条优化线分别解决了什么问题,以及 Spark 的统一内存管理模型如何在执行内存和存储内存之间做动态调配。 下图展示了 Executor 的统一内存管理模型——Execution Memory 和 Storage Memory 之间的动态借用机制: Java 对象的内存开销 一个 Java 字符串 “abcd” 在堆内占多少字节? 12345678910111213java.lang.String 对象: 对象头: 12 bytes (64-bit JVM, 压缩指针) hash: 4 bytes (int) value[]: 4 bytes ...
2026-07-13
RDD:弹性分布式数据集的五大属性
上一篇确立了 Spark 的核心是一张 DAG,而 DAG 的节点就是 RDD。这一篇进入 RDD 本身。 RDD 容易被理解成"分布式的数组"或者"分布在多台机器上的数据集合"。更准确的说法是:RDD 是一份计算配方,记录了数据从哪来、经过什么变换、丢失一个分区后怎么重算。 本文只抓一个问题:RDD 的五大属性分别控制了什么,以及这五个属性如何支撑 Spark 的调度和容错。 图 1:RDD 的五项属性分别参与计划构建与分区执行 flowchart TB R[RDD] --> P[partitions:有哪些分区] R --> D[dependencies:依赖哪些父分区] R --> C[compute:怎样计算一个分区] R --> H[partitioner:可选的键分区规则] R --> L[preferredLocations:首选位置提示] 图 1 的分区规则和位置提示用途不同:partitioner 描述键到分区的映射,preferredLocations 为调度提供位置偏好...
2026-07-13
Spark on YARN / K8s:资源管理与部署模式
Spark 应用由 Driver 和专属 Executor 组成。集群管理器分配进程所需资源,Driver 决定运行哪些 Task,Executor 读写业务数据。部署时要分别确认进程位置、控制连接、数据路径和故障后的恢复责任。 本文采用 Apache Spark 当前部署文档描述的 Standalone、YARN 和 Kubernetes 原生运行方式;具体参数应与实际安装版本对齐。Mesos 已在 Spark 4.0 移除,不属于当前可选部署后端。 生产部署拓扑与组件职责 Driver 保存 SparkContext、调度器和运行时元数据。Executor 执行 Task、缓存分区,并提供 Shuffle 数据。集群管理器既不理解 SQL 算子,也不代替 Driver 调度 Task。 图 1:资源分配、任务调度与业务数据的三条路径 flowchart TB CM[集群管理器] -->|分配资源| E[Executor 进程] D[Driver 与 SparkContext] -->|Task 与控制消息| E E -->|状态与任务结果| D ...
2026-07-13
Structured Streaming:把流当成无界表
上一篇解决了数据源 API 和谓词下推。这一篇进入流处理——Structured Streaming。 Spark 的流处理经历了两代:DStream(基于 RDD 的离散化流)和 Structured Streaming(基于 DataFrame/Dataset 的结构化流)。DStream 已经停止演进,Structured Streaming 是当前唯一推荐的流处理 API。 Structured Streaming 的核心模型可以用一句话概括:把流数据看成一张不断追加新行的无界表,复用 Spark SQL 的 Catalyst 优化器和 Tungsten 执行引擎来处理。 本文只抓一个问题:无界表模型如何工作,以及 MicroBatch 执行引擎如何把连续的流切成离散的批次。 无界表模型 12345678传统流处理的心智模型: 消息 → 处理函数 → 输出 (一条一条处理,每条消息触发一次计算)Structured Streaming 的心智模型: 数据源不断追加行到一张"输入表" 查询在整张表上持续运行 结果写入一张"输出表&qu...
Announcement
人生只是,守株待兔



