AI翻译:分布式系统编程停滞不前

来源:https://www.shadaj.me/writing/distributed-programming-stalled

在过去十年中,我们见证了分布式系统在技术上的巨大进步,但编写分布式系统的方式却鲜有根本改进。尽管我们有时能将分布式细节抽象掉(例如 Spark、Redis 等),但开发者依然在并发、容错和版本管理等问题上遇到挑战。

很多人(以及初创公司)都在致力于这个领域,但几乎所有的工作焦点都集中在开发工具上,以帮助分析使用传统(顺序)编程语言编写的分布式系统。像 Jepsen 和 Antithesis 这样的工具,已经将验证正确性和容错能力的技术水平推向了新的高度,但这些工具无法与那些原生展现分布式系统基本概念的编程模型相匹配。我们已经从 Rust 看到了这一点,Rust 所提供的内存安全保证,远比 C++ 配合 AddressSanitizer 所能提供的丰富得多。

如果你上网查询,会发现有大量框架可供编写分布式代码。在这篇博客中,我将论证这些框架仅仅是在三个固定底层范式——外部分布静态位置任意位置——之上进行权宜之计和加糖处理。而我们依然缺失一个对分布式系统来说真正 原生 的编程模型。接下来,我们将逐一探讨这些范式,然后反思一个真正分布式编程模型所欠缺的关键要素。


外部分布

外部分布 架构是绝大多数“分布式”系统的典型表现。在这种模型中,软件以 顺序逻辑 编写,并在一个具有 顺序语义 的状态管理系统上运行:

  • 无状态服务结合分布式数据库(Aurora DSQL、Cockroach)
  • 利用传播式 CRDT 状态的服务(Ditto、ElectricSQL、Redis Enterprise)
    这可能会让人感到意外。CRDT 经常被宣传为分布式系统的灵丹妙药,但另一种观点认为,它们仅仅是用来加速分布式事务。运行在 CRDT 之上的软件仍然是顺序执行的。[↩]
  • 工作流和步骤函数

这种架构编写软件非常简单,因为底层的分布式细节并未直接暴露给开发者222。至少这是理论上的情况。通常,默认并非串行化(而是采用快照隔离),因此并发错误有时会暴露出来。[↩]
尽管这种架构产出的确是一个分布式 系统,但我们并没有获得一个分布式 编程模型

由于几乎无需显式考虑容错或并发错误(除了确保选用了 CRDT 正确的一致性级别),开发者自然倾向于这种方案,因为它以简明的顺序语义屏蔽了分布式的复杂性。但这显然是有代价的:性能和扩展性都会受到影响。

对所有操作进行串行化等同于在“模拟”一个非分布式系统,只不过需要昂贵的协调协议。数据库在这种系统中形成了单点故障;你只能希望 us-east-1 不会宕机,或者切换到像 Cockroach 那样的多写入系统,但后者也自带性能上的问题。许多应用在低规模下可以容忍这种局限,但你绝不会愿意这么实现一个计数器。


静态位置

静态位置 架构是编写分布式代码的经典方式。你将多个单元组合在一起——每个单元都是以 本地(单机) 代码编写,并通过异步网络调用与其他机器进行通信:

  • 使用 API 调用进行通信的服务(可能采用 async/await,如 gRPC、REST)
  • Actor 模型(如 Akka、Ray、Orleans)
  • 通过轮询和推送共享 pub/sub 的服务(如 Kafka)

这种架构赋予了我们极大的底层控制权。我们编写的是一堆含有网络调用的顺序、单机代码,这对于性能和容错非常有利,因为我们可以控制代码在何时何地运行。

但网络单元之间的边界 僵硬且不透明。开发者必须单向地决定如何拆分应用。这些决策对正确性有深远影响:重试和消息排序由发送端控制,而接收端却常常一无所知。此外,编程语言与工具对这些单元的组合了解有限,经常无法实现跳转到定义,且服务间的序列化不匹配问题也可能悄然出现。

最重要的是,这种分布式系统设计方法根本上消除了语义共置与模块化。在顺序代码中,连续发生的操作在文本上是连续排列的,而函数调用能封装整个算法;但在静态位置架构中,开发者被迫将代码以机器为边界进行模块化,而非按照语义进行组织。在这样的架构中,根本无法将一个分布式算法封装为一个统一、完整的语义单元。

尽管静态位置架构为开发者提供了系统的最低级控制,但实际上,没有分布式系统专家的支持,要健壮地实现这类系统是极其困难的。这里存在着实现执行之间的根本矛盾:静态位置软件以单机代码形式编写,但系统正确性要求我们必须从整体上考虑整机集群的行为。构建这类系统的团队往往对并发错误和失败充满恐惧,最终使得一大堆遗留代码因过于关键而不敢轻易修改。


任意位置

任意位置 架构是大多数“现代”分布式系统方法的基础。这种架构让你可以编写看似在单机上运行的代码,但在运行时,软件会动态地在多台机器间执行333。即使 Actor 框架支持迁移,其本质上也不算数,因为开发者仍必须明确界定 Actor 的边界并指定消息传递发生的位置[↩]。

  • 分布式 SQL 引擎
  • MapReduce 框架(如 Hadoop、Spark)
  • 流处理系统(如 Flink、Spark Streaming、Storm)
  • 持久执行系统(如 Temporal、DBOS、Azure Durable Functions)

这些架构优雅地处理了语义共置的问题,因为它们在语言/API 中没有显式的网络边界来划分代码。然而,这种简化是以牺牲控制力为代价的。由于允许运行时决定代码如何分布,我们失去了有关如何扩展应用、故障域分布以及数据何时通过网络传输的决策权。

同外部分布模型一样,任意位置架构通常也伴随着性能损失。持久执行系统通常在每一步之间将状态快照到持久存储中444,尽管在处理纯确定性函数时可以进行一些优化[↩]。流处理系统可能会动态持久化数据,并在各步骤之间引入异步处理;SQL 用户则只能任由查询优化器安排,最多只能对分布式决策提供“提示”。

我们往往需要对逻辑在各个位置的分布有底层控制以保证性能和正确性。设想一下如何实现两阶段提交协议:这种协议中,领导者需要明确定义广播提案,而工作者则需要对提案作出确认。为了正确实现这样的协议,必须显式地将特定逻辑分配给相应角色,因为法定人数的确定依赖于单一领导者,而每个工作者都必须以原子方式决定接受还是拒绝提案。在任意位置架构中,实现这样一个协议几乎不可能,而不引入额外的网络和协调开销。


必备的 LLM 部分

如果你一直在关注“agentic” LLM 的动态,可能会疑问:“在我的软件由 LLM 编写的世界中,这些问题还有意义吗?”如果静态位置模型足够丰富,可以表达所有分布式系统,那编程过程中的痛苦似乎就不那么重要了。

但我认为,LLM 实际上是一个很好的论据,说明我们确实需要一个新的编程模型。这些模型在处理散布在大量文本中的上下文相关信息时,通常表现得力不从心555。参见大海捞针测试;更别说分布式系统的问题了[↩]。LLM 最擅长处理语义相关信息共置的场景。

静态位置模型迫使我们将语义相关的分布式逻辑拆分到不同模块中。LLM 目前在推理单个机器上的正确性方面已有不足,更别提将多个单机程序正确组合起来了。此外,LLM 进行决策是按顺序进行的;而将分布式逻辑拆分到多个网络模块中,本质上就与 AI 模型的结构相悖。

如果能够设计出一种保留“语义局部性”的编程模型,LLM 的表现将大为改观。设想一种编程模型,可以将跨多台机器的代码共置,那么所有分布式算法相关的逻辑都将整齐地排列在一起,LLM 就能以直线式逻辑生成分布式代码,从而大幅降低难度。

另一个关键问题是正确性。LLM 并非总是准确无误,最好的策略是结合能够自动发现错误的工具666。Lean 就是一个很好的例子,多个团队(包括 Google 及 Deepseek)已在实践中广泛应用这一理念[↩]。顺序模型无法推断分布式执行可能导致的问题,而一个足够丰富的分布式编程模型则可以揭示由于网络延迟和故障所引发的问题(可以想象成一个专为分布式系统设计的借用检查器)。


我们能从这些系统中学到什么?

尽管以上讨论的各种编程模型各自存在不少局限,但它们同时展示了原生分布式系统编程模型应具备的一些理想特性。我们能从每种模型中吸取哪些经验?

这里我将略过外部分布模型,因为如前所述,其并非真正意义上的分布式。对于那些能够容忍这种模型的性能及语义限制的应用,外部分布是一个不错的选择;但对于通用的分布式编程模型,我们不能将网络和并发完全隐藏在开发者视野之外。

静态位置模型似乎是一个合适的起点,因为它至少能够表达出我们可能希望实现的所有类型的分布式系统,尽管这种编程模型在帮助我们推理分布式问题上力有不逮。而我们从任意位置模型中所缺失的两点分别是:

  • 将分布于多台机器的逻辑放在同一个函数中顺次编写
  • 将诸如消息乱序、重试以及跨网络边界的序列化格式等分布式行为的语义信息暴露出来

而每一点都有其对应的另一面,这是我们不愿失去的:

  • 显式控制逻辑在各个机器上的放置,并能够执行本地、原子化的计算
  • 在不迫使语言绑定全局协调与恢复协议的前提下,提供丰富的容错保证和网络语义选项

是时候推出一个原生的编程模型了 —— 类似于为分布式系统打造的 Rust —— 来应对上述所有挑战。

感谢 Tyler HouJoe HellersteinRamnivas Laddad 对本文的反馈!


  1. CRDT 经常被宣传为分布式系统的灵丹妙药,但另一种观点认为,它们仅仅是用来加速分布式事务。运行在 CRDT 之上的软件依然是顺序执行的。[↩]
  2. 至少这是理论上的设想。默认情况下,并非采用串行化(而是快照隔离),因此有时会暴露出并发错误。[↩]
  3. 即使 Actor 框架支持状态迁移,其本质也不能完全忽略开发者必须显式定义 Actor 边界以及消息传递位置的事实。[↩]
  4. 对于纯确定性函数的步骤,可做一些优化处理。[↩]
  5. 参见大海捞针测试;分布式系统的推理更具挑战性。[↩]
  6. Lean 是这方面的优秀实践。多个团队(包括 Google 与 Deepseek)已在此领域展开应用研究。[↩]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/890937.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第一周实验:二次开发

来源 来自大一舍友C++大作业。该项目模拟了一个图书管理系统,涉及到用户对于书籍的查看、借阅与归还,管理员对于书籍相关信息的增删改查。 运行环境+运行结果的截图 运行环境:Windows 11 + Visual Studio 2022main.cpp #include<Windows.h> #include "Account.h&…

学习笔记之day02 Linux-基础篇-系统安装

​1、操作系统简介操作系统:人与计算机硬件交互的中介Linux:内核+Shell +扩展软件Windows:内核+explorer.exe+软件类比法:计算机硬件 -- 内核 == 蛋黄 / Shell == 蛋清 / 外围应用程序 == 蛋壳常见的操作系统:Windows、Linux、DOS、UnixLinux操作系统开放源代码、可以自由…

绝缘电阻测试仪科普

什么是绝缘电阻绝缘电阻是指两个绝缘介质间的电阻,当另一端安装有电压源时,绝缘介质内电荷不能流动,因而受电压源作用,在另一端产生电势差,形成电阻抵消电压势差而不致使电荷漏出。一般情况下,绝缘电阻越大,电气设备的安全性就越好,缺陷率也越低。 为什么测量绝缘电阻绝…

【CodeForces训练记录】Educational Codeforces Round 175 (Rated for Div. 2)

训练情况赛后反思 CD连续卡题,D题树上层序遍历+加法原理,鉴定为基本的图论数据结构没学好 A题 直接打表,对于 i%3 = i%5 的情况,我们发现有三个一组,三个一组连续的数,每组第一个数之间差 15,所以我们 / 15 * 3 先把整组的数量算出来,再求是组内第几个,就能得到答案了…

软工五问

这个作业属于哪个课程 课程链接这个作业要求在哪里 作业要求这个作业的目标 学习使用markdown, 接触GitHub, 建立个人博客个人介绍 📋标签 广东湛江 人 期望成为 golang后端工程师 学习经历持续学习golang及其框架, 设计模式 持续学习后端各个组件的可靠高效解决方案兴趣爱好…

清华大学推出的5册免费的 DeepSeek 学习使用指南!

前言 在当今这个信息洪流、技术飞速迭代的时代,DeepSeek的横空出世极大地降低了普通人利用人工智能技术的门槛。然而,尽管机遇就在眼前,仍有不少朋友面对DeepSeek感到无从下手,不知如何利用它来紧握时代赋予的红利。对此,清华大学展现出了高度的社会责任感与前瞻性,推出了…

拆解分析行业头部米家绿米燃气报警器怎么样?

小米绿米天然气卫士拆解,内置Zigbee模组,需要连接Zigbee 3.0网关 或者 具备Zigbee 3.0网关功能的设备报警 天然气是每家每户日常生活中都会使用到的清洁能源,因此对于天然气的安全防护时刻不能放松。小米天然气卫士是小米与业内知名品牌 赛特威尔 联手打造的一款产品,可探测…

C++ DLL 供 C# AnyCPU 调用 【 OpenCV onnxruntime】

背景 C++ 打包的DLL用到 OpenCV,用到 onnxruntime C# 软件需要打包成Any CPU版本,即可以在 x86下使用,也可以在x64下使用 C# 前端想把 C++ dll与依赖放在单独的”Libs“文件夹中,不是"Dubug"下 难点: 在C++ 中, OpenCV 和 onnxruntime 分别有x64和x86两个版本,…

Mac本地部署DeepSeek(简洁版)

1. 下载ollama2. 安装ollma 无脑安装那么最小的1.5b模型就拥有15亿的参数量,而最大的671b则有6710亿个参数,我们要使用的是前面这6个规模较小的模型。ollama run deepseek-r1:8b要等一会我不相信黑夜将至 因为火把就在我的手中。

使用OpenLPA编辑eUICC卡片

使用OpenLPA编辑eUICC卡片原文地址: [https://github.com/EsimMoe/MiniLPA/blob/main/README_zh-CN.md] 原作者:EsimMoe 许可: AGPL-3.0 license精美的现代化 LPA UI特性良好的跨平台支持 (Windows, Linux, macOS) 更友好的用户界面 i18n 多语言支持 搜索与快捷跳转 自由地管理…

UltraRAG 框架全家桶

转载:清华等团队推出 UltraRAG 框架全家桶,让大模型读懂善用知识库!引言 RAG 系统的搭建与优化是一项庞大且复杂的系统工程,通常需要兼顾测试制定、检索调优、模型调优等关键环节,繁琐的工作流程往往让人无从下手。 近日,针对以上痛点,清华大学 THUNLP 团队联合东北大学…

2024/2/27日 日志 第一次测试案例分析(4)--登录与注册和仓库方面

UserMapper点击查看代码 package com.Moonbeams.mapper;import com.Moonbeams.pojo.User; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotation…