DAG Scheduler 与 Task Scheduler:从逻辑计划到物理执行
上一篇解决了 Stage 的划分规则——遇到 ShuffleDependency 就切一刀。这一篇进入调度器内部。 Stage 划分出来之后,谁来决定 Stage 的提交顺序?谁来把 Stage 拆成 Task 发给 Executor?Spark 用两层调度器分工完成这件事:DAGScheduler 负责 Stage 级别的依赖分析和提交顺序,TaskScheduler 负责 Task 级别的资源分配和执行调度。 本文只抓一个问题:一个 action 触发之后,从 Job 到 Stage 到 Task 再到 Executor,调度链路上每一步发生了什么。 调度全景 12345678910111213141516171819202122232425用户代码: rdd.count() │ ▼ SparkContext.runJob() │ ▼ DAGScheduler.submitJob() │ 构建 Stage DAG,按依赖顺序提交 ▼ DAGScheduler.submitStage() │ 检查父 S...
宽依赖与窄依赖:Stage 是怎样划分出来的
上一篇拆解了 RDD 的五大属性,其中 dependencies 决定了 RDD 之间的依赖类型。这一篇进入依赖类型的核心区分——宽依赖和窄依赖——以及它如何直接决定 Stage 的划分。 宽依赖和窄依赖容易被理解成"一对一"和"多对多"的分区关系。更准确的说法是:窄依赖意味着子 RDD 的每个分区只依赖父 RDD 的固定少数分区,可以在单个 Task 内完成计算;宽依赖意味着子 RDD 的分区需要读取父 RDD 所有分区的数据,必须等待一次全量数据交换(Shuffle)。 本文只抓一个问题:DAGScheduler 按什么规则把 RDD 依赖图切分成 Stage。 下图展示了 Stage 划分的核心规则——窄依赖 pipeline 执行,宽依赖切出新 Stage: 窄依赖的三种形态 窄依赖(NarrowDependency)的定义是:父 RDD 的每个分区最多被子 RDD 的一个分区使用。在 Spark 源码中,NarrowDependency 有两个具体子类: OneToOneDependency:父子分区一一对应。map、filte...
RDD:弹性分布式数据集的五大属性
上一篇确立了 Spark 的核心是一张 DAG,而 DAG 的节点就是 RDD。这一篇进入 RDD 本身。 RDD 容易被理解成"分布式的数组"或者"分布在多台机器上的数据集合"。更准确的说法是:RDD 是一份计算配方,记录了数据从哪来、经过什么变换、丢失一个分区后怎么重算。 本文只抓一个问题:RDD 的五大属性分别控制了什么,以及这五个属性如何支撑 Spark 的调度和容错。 五大属性总览 Spark 源码中 RDD 的抽象类定义了五个方法,每个方法对应一个核心属性: 123456RDD[T]├── getPartitions: Array[Partition] ← 数据怎么切分├── getDependencies: Seq[Dependency[_]] ← 上游是谁├── compute(split, context): Iterator[T] ← 一个分区怎么算├── partitioner: Option[Partitioner] ← 按什么规则分区└── getPreferredLocations(s...
导读:为什么 Spark 的核心是一张 DAG
Spark 常被介绍为"比 MapReduce 快 100 倍的计算引擎"。这个说法把重点放错了地方。速度差异只是结果,不是原因。真正的区别在于执行模型:MapReduce 是一条固定的 Map-Shuffle-Reduce 三段流水线,而 Spark 是一个可以表达任意有向无环图(DAG)的执行引擎。 本篇只抓一个问题:Spark 的 DAG 执行模型到底和 MapReduce 的线性管道有什么本质区别,以及这个区别如何贯穿整个系列。 MapReduce 的线性管道 MapReduce 的执行模型可以用一句话概括:读数据 → Map → 写磁盘 → Shuffle → 写磁盘 → Reduce → 写数据。 1HDFS → Map Task → Local Disk → Shuffle → Local Disk → Reduce Task → HDFS 这条管道有两个结构性约束: 第一,每个 MapReduce 作业只有一轮 Map 和一轮 Reduce。如果业务逻辑需要多轮聚合(比如先按用户分组,再按地区汇总),就必须把逻辑拆成多个 MapReduce 作...
从规则到统计:人工智能七十年的两条路线之争
人工智能的历史,本质上是一部关于"什么是智能"的争论史。 从 1950 年代至今,这个领域经历了至少两次大规模繁荣和两次寒冬,催生了符号主义、连接主义、统计学习、深度学习、强化学习等多个范式。这些范式的兴衰,表面上看是技术路线的竞争,底层驱动力却是对一个哲学问题的不同回答:智能究竟是"规则的执行"还是"数据的涌现"? 一、两种智能观的源头 1.1 符号主义:智能就是符号操作 1943 年,Warren McCulloch 和 Walter Pitts 发表了一篇论文,用数理逻辑描述神经元的行为。这篇论文同时启发了两个方向——一个方向关注"逻辑"本身,另一个方向关注"神经元网络"本身。前者演化为符号主义(Symbolism),后者演化为连接主义(Connectionism)。 符号主义的哲学根基可以追溯到莱布尼茨。莱布尼茨试图创建一种"通用逻辑演算"来表达所有人类思想,17 世纪的霍布斯则主张推理"不过是计算"。这条线索在 20 世纪中叶被 ...
美日开战之前,美国偏袒过日本吗——核查"日本子弹七成靠美国"的说法
九一八之后,尤其是七七事变之后,中文世界一直流传一种说法:美国一边在道义上谴责日本侵略,一边继续跟日本做生意,卖给日本的石油、废钢比卖给中国的还多,所以日本用来打中国的子弹,“七成以上其实是美国人间接造的”。这个判断在情绪上很有冲击力,在朋友圈和短视频里反复出现,但它有两个一直没被认真处理的问题:第一,那个"七成"到底是怎么算出来的,是不是一个能站住的统计;第二,"美国偏袒日本"这个定性,能不能被美方自己的贸易数据和政策档案支持。 把这两个问题拆开看,结论并不是简单的"是"或"否"。事实内核大体成立——直到 1940 年,美国确实是给日本战争机器输血最多的国家,而且这种输血在南京大屠杀之后又持续了整整三年。但"偏袒"这个定性,以及"七成子弹"这个具体数字,都需要修正。美国不是在"援助"日本,而是在一套孤立主义的自由贸易法律框架下"卖货"给日本;与此同时,它是最早拒绝承认日本征服成果的大国,一直在给中国放贷款,并且从 193...
AI 是放大器不是方向:读 Adam Bender 谈软件生态学的 10 倍时刻
引子:10 倍代码不等于 10 倍工程 Google 首席软件工程师 Adam Bender 在 Google I/O 2026 的一场演讲里抛出大多数人还没来得及思考的问题:当 AI 把代码产出速度推到现有工程流程无法承载的地步,开发者生态系统里什么会最先垮掉? 他的回答直白:今天构建软件的方式,在 10 倍速度下根本行不通。AI 时代的真正赢家不是产出最高的团队,而是基本功最扎实的那些人。AI 只负责放大,不负责方向。 这场演讲串起一个大多数人没听过的概念:软件生态学,对生产软件的社会技术生态系统进行整体性研究的学科。它要求不只看技术,还要看人、看文化、看组织里那些不成文的规则。 flowchart TB subgraph Eco["社会技术生态系统(软件生态学的研究对象)"] direction LR Culture["工程文化<br/>组织结构 · 激励机制"] Practice["工程实践<br/>审查 · 测试 · 发布"] ...
CI/CD 方法论的前世今生
软件工程有一条反直觉的规律:集成的频率越高,每次集成的痛苦越小。这条规律从 1990 年代末被 Kent Beck 写进极限编程的实践清单,到今天演化出一整套涵盖构建、测试、部署、发布的自动化体系。CI/CD 不是某一个工具或某一种流程,而是三十年工程实践反复迭代的产物。 持续集成的诞生(1996-2006) 极限编程与 CI 的起源 1996 年,Kent Beck 加入克莱斯勒公司的 C3(Chrysler Comprehensive Compensation System)项目。这个项目此前陷入僵局,Beck 将它作为极限编程(XP)的试验田,引入了十二条核心实践,持续集成是其中之一。CI 的核心主张很简单:开发者每天多次将代码集成到主干,每次集成都触发自动构建和测试。1999 年出版的《Extreme Programming Explained: Embrace Change》正式将 CI 确立为一个命名实践。 CI 要解决的问题在当时有一个形象的说法叫"集成地狱"(integration hell)——团队各自开发数周甚至数月,最后合并代码时发现冲突...
MySQL 经典架构模式:从主从复制到分库分表
MySQL 在绝大多数业务系统中扮演事实源的角色。Redis 和 ES 都是派生存储——数据可以从 MySQL 重建,反过来不行。围绕 MySQL 的架构模式,核心问题始终是三个:怎么扛住读写压力、怎么保证数据不丢、怎么随业务增长水平扩展。 下面整理十个生产环境中反复出现的 MySQL 架构模式。和 ES 架构模式 与 Redis 用例全解 形成三件套:Redis 管热路径和派生状态,ES 管可搜索的派生索引,MySQL 管事实。 模式速查 模式 解决的问题 核心机制 典型场景 主从复制 + 读写分离 读压力分摊 binlog 复制 + 代理层路由 读多写少的业务 半同步复制 + 增强半同步 主从切换时数据不丢 after-sync / after-commit 金融、订单 双主(互为主从) 机房级故障切换 双向复制 + 自增步长错开 同城双活 级联复制 大规模从库扩展 从库的从库 读流量极大的分析场景 分库分表 单库容量和写入瓶颈 水平分片 + 路由中间件 亿级数据量 影子表与 Online DDL 大表结构变更不锁表 pt-osc / gh...
Elasticsearch 经典架构模式:从时序索引到跨集群检索
Elasticsearch 不只是一个搜索引擎。围绕它的分片、副本、别名、ILM 等原语,生产环境中沉淀出了一批反复出现的架构模式。这些模式解决的问题各不相同——有的管数据生命周期,有的管多租户隔离,有的管读写分离——但核心思路一致:用 ES 的原语组合出业务需要的数据分布和访问路径。 下面整理十个常见的 ES 架构模式。“时间分区索引 + 别名滚动”——每月一个物理索引、基于别名查询、定期淘汰老索引——是日志和时序场景的基石,配置也最精细,放在第一个。 模式速查 模式 解决的问题 核心原语 典型场景 时间分区索引 + 别名滚动 数据无限增长的生命周期管理 Index Template + Alias + ILM/Rollover 日志、订单流水、审计 冷热分层存储 不同时效数据的成本优化 Node Attribute + Allocation Filter + ILM 日志、监控指标 读写分离 写入不影响搜索延迟 写别名 + 读别名 + Replica 调度 高写入吞吐 + 低延迟搜索 多租户索引隔离 租户间数据和性能隔离 Index-per-ten...







