用动画展示 Postgres 16 与 etcd 的亚稳态故障
Animations for System Builders
Marc Brooker 介绍用动画帮助系统构建者理解系统行为,并以 Postgres 16 和 etcd 的真实测试轨迹展示亚稳态故障。
文章将真实测试轨迹转成动画,呈现负载峰值如何触发亚稳态循环,也为解释复杂系统故障提供了可复用路径。
关于我
我叫 Marc Brooker。我喜欢打造真正能用的东西,也喜欢做些酷炫的事。我喜欢构建大型系统。我也会涉猎机械加工、焊接、烹饪和滑雪。
我目前在西雅图担任 Amazon Web Services (AWS) 的工程师,负责智能体 AI,尤其关注智能体 AI 的安全与政策。此前,我从事过 EC2、EBS、数据库、无服务器和无服务器数据库方面的工作。
所有观点均仅代表我本人。
链接
我的出版物和视频
Mastodon 上的 @marcbrooker
Twitter 上的 @MarcJBrooker
或许漂亮的图片能帮助我们学习?
我喜欢用 LLM 来帮助自己更好地理解系统。在我所写的 Strands Decider 博文中,我提到自己经常会对它说问我一些问题,以确认我理解了这一点。我目前还很享受的另一种技巧——也很高兴看到身边的人开始使用——就是制作动画。
动画可以帮助我们凭直觉理解系统如何及为何运作,或如何及为何失效。
这里有一个例子:你知道吗,如果 Raft 集群中哪怕有一个成员的存储层就 fsync() 撒谎,集群就可能丢失写入?
当我构建 Stability Sim 时,我希望帮助工程师更好地理解亚稳态故障。在抽象层面上,这一做法效果相当不错(例如,重试和队列很容易触发亚稳态),但我仍听到有人怀疑这些行为会出现在真实系统中。毕竟,这些真实系统已经过生产环境验证;如果这些行为真的存在,难道我们早就已经把它们排查出来了吗?
我们先从 Postgres 开始。
这个例子采集自真实 MicroVM 中运行的 Postgres 16 的跟踪记录。负载峰值出现之前,得益于整个工作集都驻留在页缓存中,数据库能够轻松应对 20 queries-per-second 的负载。但负载峰值之后,运行查询占用了大量内存(每个查询占用 12MB),如今这些查询改由磁盘而非页缓存提供数据,因此运行速度变慢。我喜欢这个例子,因为它表明,即使简单的非分布式系统也会出现这些行为。
那 etcd 呢?
这里同样是负载峰值触发了亚稳态,只不过这次是写入。过载的节点看起来像是不可用,从而引发应用级重发风暴。我喜欢这个例子,因为 etcd 是广泛使用的优质软件。运维经验似乎并不能有效暴露这类问题。
当我写 垃圾回收与亚稳态 时,一位广为人知的系统领域学者告诉我,那是幻想。我曾在现实场景中亲眼看到它以无法分享的方式发生;而且,鉴于那篇博文中的说法只是泛泛而谈,我可以原谅人们不相信这种情况会发生。
所以,有了一个来自真实世界的例子就很好,这次再拿 etcd 开开刀。
一开始,我们以 500 reads/second 的速度顺利运行,随后负载峰值达到 1000 reads/s。读取峰值增加了 GC 所耗费的时间,延长了平均存留时间,并使可用于读取工作负载的 CPU 减少。这是一个自我强化的循环;如果没有外部干预,系统就无法恢复。
我认为,由于分配器的工作量不断增加,没有 GC 的运行时上也可能出现同样的情况,但我还未能复现。
这里的动画均由 Kiro 和 KiroCrew 生成,主要使用 Opus 5.5。实际结果来自真实的测试环境,该环境会捕获为动画提供依据的追踪记录。
来源:Hacker News · brooker.co.za