互联网史上最长宕机:AWS DynamoDB 故障深度解析 Peter Pang 2025-10-31

宕机肇始与连锁反应

2025年10月19日晚上11:48,正准备休息的AWS员工迎来了一则噩耗:核心数据库产品 DynamoDB 出现了连接故障。这一故障直接导致依赖它的上百个云服务产品随之下线。最初的故障源自一个被形容为“教科书式”的 Race Condition(竞态条件),即两个修改数据的命令前后冲突,最终导致了数据库连接问题。

尽管工程师们在3个小时内迅速修复了 DynamoDBRace Condition 漏洞,但灾难并未就此结束。作为 AWS 最引以为豪的产品之一,DynamoDB 几乎是所有内部系统的默认数据库。因此,在这3个小时的宕机期间,大量系统累积了无数需要重试的任务。其中就包括负责调度所有 EC2 服务器资源的内部管理程序——Droplet WorkFlow Manager(DWFM)

2025年10月20日凌晨2:25,在 DynamoDB 恢复的那一瞬间,DWFM 被堆积如山的待办事项瞬间冲垮,导致调度中心宕机,进而引发所有 EC2 服务器无法启动。这再次凸显了重试机制设计上的缺陷。更令人担忧的是,如此重要的程序竟然没有自动恢复机制;赶来修复的工程师甚至没有一份可以参考的手动恢复流程,这表明 AWS 内部在此之前从未认真考虑过“如果 DWFM 挂了该怎么办”的极端场景。

直到凌晨5:28,DWFM 才得以恢复,EC2 服务器也开始正常启动。然而,旁边的 Network Manager(网络管理器),一个负责掌控所有 EC2 网络功能的程序,此刻却累积了长达6个小时的待办事项。加上刚大量重启的 EC2 发出的海量新请求,其处理速度已不足以应对新增任务,工程师们只能再次手动 SSH 进去进行疏导。直到早上10:36,积压的待办事项才处理完毕,EC2 的网络功能才恢复正常。

几乎在同一时间,负责分配网络流量的负载均衡器 NLB(Network Load Balancer)也开始为重启的 EC2 服务器引流。但由于 Network Manager 的卡顿,部分 EC2 服务器时而可联系,时而无法联系,导致 NLB 的健康检查在红灯和绿灯间反复横跳,并引发 DNS 的反复下架和上架。忍无可忍的工程师们在9:36被迫关闭了 NLB 的健康检查,使其忽略无响应服务器,暂时维持绿色状态。直到下午2:09,所有积压的 EC2 服务器才恢复正常,NLB 的健康检查重启,网络功能才最终全面恢复。2:20,最后一批受影响的容器服务 ECSEKS 也恢复正常,此次长达14小时32分钟的瘫痪事故宣告结束,成为有记录以来云服务行业历时最长的一次大规模宕机。

Race Condition 根源剖析

与早期Google Cloud的瘫痪事故相比,AWS 本次事故的“草台”程度相对较低。除了最开始的导火索,大部分问题源于错综复杂的架构导致的连锁反应以及系统体量过大产生的极端高负荷压力。巧合的是,这两次瘫痪事故的导火索都是入门级的代码错误。

本次 AWS 事故的源头,是 DynamoDB 系统中负责处理 DNS 的两个程序:负责生成 DNS 记录的 planner 和负责将新记录写入 DNS 系统的 enactor。为了保证容错,DynamoDB 在三个可用区部署了三个独立的 enactor。每当 planner 生成一个新记录,其中一个 enactor 就会获取并尝试写入 DNS。在写入前,enactor 会进行一个前期检查,确保它手上的记录比当前 DNS 中的更新;写入成功后,还会执行一个清理动作,抹掉 DNS 中比其刚写入记录更早的那些记录。

在10月19日晚上,出现了一个极端情况:enactor 张三首先从 planner 拿到记录A,在写入 DNS 时遇到了延迟,暂时停滞。此时,planner 又生成了记录B。enactor 李四拿到记录B并顺利写入 DNS。就在李四准备执行清理动作时,张三的延迟结束,继续执行任务,将记录A写入 DNS,覆盖了记录B。随后,李四开始清理,发现 DNS 中比它刚写入的记录B更早的记录是A,于是按照代码逻辑将记录A抹掉。当张三和李四都完成任务后,指向 DynamoDB 域名的 DNS 记录变得为空。此时,planner 生成了新记录C,enactor 王五拿到记录C准备写入,却在前期检查阶段被卡住——因为 DNS 中没有记录,无法与记录C进行对比。逻辑因此进入死胡同,无论 planner 后续生成多少新记录,都没有 enactor 能成功写入 DNSDynamoDB 的域名从互联网上彻底消失,导致其下属产品也随之瘫痪。这个错误,相较于Google Cloud忘记写 try catch 导致 NullPointerException,仅是“好一点点”。

演讲者提出,DynamoDB 的这个 Race Condition 问题,其根源在于架构设计。在“多个进程修改同一个数据”的场景下,不应将“保证数据完整性”的任务放在进程本身,而应由数据的接收和储存方承担,即 DNS 系统 Route53,作为 single point of truth。让每个 enactor 都进行事前事后检查和清理,无论代码多严谨,都是不合理的决定,因为 ACID(原子性、一致性、隔离性、持久性)本来就极难完美达成。

成本、风险与纳什均衡

AWS 形成鲜明对比的是,微软的云服务 Azure 在制作本期视频时,也正经历全球范围的宕机,这已是 Azure 当年的第五次世界级故障。然而 Azure 的新闻曝光度远低于 AWS,部分原因在于其大客户多为传统行业巨头,普通民众感知不深。但仔细分析其故障报告,会发现 Azure 的问题多集中在 CDN(内容分发网络)运维失误、DDoS(分布式拒绝服务攻击)或两者结合,很少出现拖垮整个体系的严重连锁反应。

AWS 的风格则截然不同,正如早期视频提到的,AWS 崇尚微服务架构,倾向于使用现成服务而非自建轮子。久而久之,服务间的高度耦合使得“牵一发而动全身”。本次事故中,DynamoDB 拖垮 DWFMDWFM 拖垮 EC2EC2 拖垮 NLB 的连锁反应,完美体现了 AWS 内部系统“同生共死”的状态。回顾 AWS 历史上的大规模瘫痪事故,导火索多是 DynamoDBS3Lambda 等通用存储和计算服务,这些服务是绝大多数 AWS 产品的基础,因此被微服务架构的原则紧密串联。

一个敏锐的观察是,包括本次事故在内,AWS 的重大故障似乎总发生在“us-east-1”分区。这引出了一个核心疑问:云服务主打的分布式部署、高容错和稳定性,为何一个分区出故障就能拖垮半个互联网?虽然云服务在市场营销中常与分布式、高容错挂钩,但这仅仅是提供了搭建高容错系统架构的环境,实际是否搭建取决于用户。即使是 AWS 自己,也未能完全遵循此原则,例如其管理权限系统 IAM(身份与访问管理),只在 us-east-1 分区设有写入节点,其余分区仅为只读节点。

而对于大多数企业而言,最关键的问题是:是否愿意投入额外成本进行多点部署?这本质上是一个商业问题。技术上,multi-node(多节点)、multi-region(多区域)、multi-cloud(多云)等容错方案已相当成熟,多数云服务商均提供开箱即用的服务。然而,“钱”是关键症结:两个节点意味着两倍成本,两个区域四倍,两个云八倍。如果CEO面前有一个按钮,按下可避免几年一次、持续数小时的全面瘫痪,但代价是成本翻八倍,多数CEO可能不会按下。

这其实是一个博弈论问题。对企业而言,最怕的不是自家产品出问题,而是“只有自家产品出问题”。若集体出问题,媒体会归咎于云服务商,企业仅是受害者。这种几年一次的事故,对大众而言已属 black swan event(黑天鹅事件)。即使投入巨额成本做好容错,逃过一劫,也不会因此获得表扬,例如此次事故中毫发无损的 Netflix,作为 AWS 最大客户、模范生,其表现也“nobody cares”(无人关注)。

因此,从CEO视角看,更关心用户和股民的反应,最优解就是采取与其他企业相同的做法。AWS 最早成立、功能最快、资源最丰富的 us-east-1 分区,吸引了早期企业集中部署,后来者也自然将其视为首选乃至唯一选择。结果是所有人都在 us-east-1 上“抱团,同生共死”,形成了一个完美的 Nash equilibrium(纳什均衡)。

尽管作为程序员,看到技术被如此“糟蹋”会感到气愤,但从宏观上看,无论是 AWS 内部产品间的互相捆绑,还是用户扎堆在单一分区部署,这些决定可能不是最科学的,但无疑是最现实的。技术人追求完美,但世界并非围绕技术运转,技术只是服务于世界的工具。归根到底,我们都只是工具人。

📌 文中提及的人物和组织

关键字: cloud-computing system-failure-analysis software-architecture risk-management devops-practices