分布式系统中只有两个难题(上)

简介: 分布式系统中只有两个难题(上)

3 分布式系统抽象

讨论编程语言时,我们使用通用术语并用函数、运算符、类、变量和指针来定义我们的程序。通用的词汇可以帮助我们避免每次都为了描述某些东西而发明新词。我们的定义越精确、越没有歧异,听众也就越容易理解。

在开始学习算法之前,我们首先要了解分布式系统中的词汇:这些定义你会经常在演讲、书籍和论文中遇到。


链路

网络是不可靠的:消息会丢失、延迟或被打乱。记住这一点之后,我们来尝试构建几种通信协议。我们从最不可靠的协议开始,确定它们可能处于的状态,然后找出可以为协议增加的东西使它提供更好的保证。


公平损失链路

我们可以从两个进程开始,它们之间以链路相连。进程可以相互发送消息,如图2所示。任何通信介质都是不完美的,消息可能丢失或延迟。

看看我们能得到什么样的保证。消息M被发送之后(从发送方的角度来看),它可能处于以下状态之一:

  • 还未送达进程B(但会在某个时间点送达)
  • 在途中丢失且不可恢复
  • 成功送达远程进程


image.png


注意,发送方没有任何方法确定消息是否已经送达。在分布式系统的术语中,这种链路称为公平损失(fair-loss)。这种链路具有以下属性:


公平损失

       如果发送方和接收方都是正确的,且发送方无限多次重复发送,则消息最终会被送达注3。

有限重复

       发送的消息不会被送达无限次。

不会无中生有

       链路不会自己生成消息。换句话说,它不会传递一个从未发送过的消息。


公平损失链路是一种很有用的抽象,它是构建具有更强保证的通信协议的基石。我们可以假设该链路不会在通信双方之间系统性地丢弃消息,也不会创建新消息。但与此同时,我们也不能完全依靠它。这可能让你想起了用户数据报协议(UDP),UDP允许我们从一个进程发送消息到另一个进程,但在协议层面上不提供可靠的传输语义。


消息确认


为了改善这一情况、更清晰地获得消息状态,我们可以引入确认(acknowledgment)机制:接收方通知发送方消息已送达。为此,我们需要双向通信信道,并增加一些措施以区分不同的消息,例如序列号—单调递增的唯一消息标识符。


每个消息只要有唯一标识符就足够了。序列号只是唯一标识符的一种特殊情况,即使用计数器来获取标识符,从而实现唯一性。当使用哈希算法来唯一地标识消息时,我们应当考虑可能的冲突,并确保能消除歧义。


现在,进程A可以发送消息M(n),其中n是单调递增的消息计数器。B收到消息后立即向A发送确认ACK(n)。图8-3展示了这种通信形式。


image.png


确认消息,就像原始消息一样,也有可能在途中丢失。消息可能处于的状态数会稍有变化。在A收到确认之前,该消息仍处于我们前面提到的三种状态之一,但是,一旦A收到确认,就可以确信该消息已送达B。


消息重传



增加确认机制仍不足以保证通信协议完全可靠:发送的消息仍可能会丢失,远程进程也可能在确认之前发生故障。为了解决该问题并提供送达保证,我们可以尝试重传(retransmit)。重传是指发送方重试可能失败的操作。我们之所以说可能失败,是因为发送方并不能真的知道有没有失败,因为我们要讨论的链路不使用确认机制。


进程A发送消息M之后,它将等到超时T被触发,然后尝试再次发送同一条消息。假设进程之间的链路完好无损,进程间的网络分区不会无限持续下去,并且并非所有数据包都丢失,我们可以认为,从发送方的角度看,消息要么尚未送达进程B,要么已经成功送达。由于A一直在尝试发送消息,可以认为传输过程中不会发生不可恢复的消息丢失。




在分布式系统的术语中,这种抽象称为顽固链路(stubborn link)。之所以称为顽固,是因为发件人会无限期地反复发送消息,但是,由于这种抽象非常不切实际,因此我们需要将重试与确认结合起来。


重传的问题

每当我们发送消息时,在收到远程进程的确认之前,我们无从得知消息的状态:可能已被处理,可能马上就要处理,也可能已经丢失,甚至可能在收到消息之前远程进程就崩溃了—上述的任意状态都是可能的。我们可以重试操作、再次发送消息,但这可能导致消息重复。只有当我们要执行的操作是幂等时,处理重复消息才是安全的。


幂等(idempotent)的操作可以执行多次而产生相同的结果,且不会产生其他副作用。例如,服务器关机操作可以是幂等的,第一次调用将发起关机,而所有后续调用都不会产生任何其他影响。


如果每个操作都是幂等的,那我们可以少考虑一些传递语义,更多地依赖重传来实现容错,并以完全反应式的方式构建系统:为某些信号触发相应的操作,而不会引起预期之外的副作用。但是,操作不一定是幂等的,简单地假设它们幂等可能会导致集群范围的副作用。例如,向客户的信用卡收费不是幂等操作,绝对不可以重复收费多次。


在存在部分故障和网络分区的情况下,幂等性尤其重要,因为我们无法总是确定远程操作的确切状态—是成功还是失败,还是会马上被执行—我们只能等待更长的时间。保证每个操作都是幂等的是不切实际的,因此我们需要在不改变实际操作语义的情况下,提供与幂等性等价的保证。为此,我们可以使用去重来避免多次处理消息。



相关文章
|
5月前
|
人工智能 供应链 数据可视化
一文读懂AI引擎与Together规则引擎重塑智能决策
从1950年图灵提出人工智能设想到如今AI引擎实现自主决策,Together规则引擎正成为智能决策核心。它通过动态规划、多工具调用与持续学习机制,赋能供应链、财务、定价等场景,提升决策透明度与效率。Together助力AI引擎突破落地瓶颈,推动企业管理迈向“决策即服务”新时代。
|
11月前
|
人工智能 自然语言处理 Java
对话即服务:Spring Boot整合MCP让你的CRUD系统秒变AI助手
本文介绍了如何通过Model Context Protocol (MCP) 协议将传统Spring Boot服务改造为支持AI交互的智能系统。MCP作为“万能适配器”,让AI以统一方式与多种服务和数据源交互,降低开发复杂度。文章以图书管理服务为例,详细说明了引入依赖、配置MCP服务器、改造服务方法(注解方式或函数Bean方式)及接口测试的全流程。最终实现用户通过自然语言查询数据库的功能,展示了MCP在简化AI集成、提升系统易用性方面的价值。未来,“对话即服务”有望成为主流开发范式。
7994 7
|
3月前
|
SQL 人工智能 数据挖掘
拒绝"数字坟墓":如何用AI让沉睡的数据开口说话?
很多数据报告沦为"数字坟墓",核心在于缺乏从数据到洞察的翻译。本文提供一套"数据分析报告生成指令",帮助开发者和分析师利用AI跨越技术与商业的鸿沟,将枯燥报表转化为驱动决策的行动指南。
188 4
|
7月前
|
机器学习/深度学习 设计模式 人工智能
workflow is all you need?探讨乐高式流程编排能否实现任意Multi-Agent模式
阿里集团安全部探索利用AI工作流(workflow)构建多智能体系统(MAS),以提升网络安全领域的创造性协作能力。文章围绕“Workflow is All You Need”这一核心观点,分析当前主流AI Workflow产品是否具备支持多种MAS协作模式的能力。通过Dify等工具演示了单Agent、路由、顺序执行、主从控制、反思、辩论、群聊等多种典型协作模式的实现方式,并指出现有平台在异步交互、动态扩展及并行化MOA模式上的局限性。最终强调,尽管目前尚存挑战,但AI Workflow仍是快速搭建多智能体系统的有效路径。
workflow is all you need?探讨乐高式流程编排能否实现任意Multi-Agent模式
|
Java 开发者
深入理解BigDecimal:精度保障的秘诀
【10月更文挑战第29天】
485 5
|
机器学习/深度学习 人工智能 Linux
【机器学习】Dify:AI智能体开发平台版本升级
【机器学习】Dify:AI智能体开发平台版本升级
1676 0
|
缓存 监控 安全
使用GraphQL构建高效数据查询:技术深度剖析与实践
【8月更文挑战第11天】GraphQL以其强大的灵活性和高效性,为现代Web开发提供了一种全新的数据查询和传输方式。通过合理使用GraphQL的核心特性和策略,开发者可以构建出高效、灵活且易于维护的API。然而,GraphQL的成功应用也需要开发者在Schema设计、查询优化、客户端缓存以及安全性等方面进行深入的思考和实践。希望本文能够为开发者在使用GraphQL构建高效数据查询方面提供一些有益的参考和启示。
|
Kubernetes Cloud Native Java
灰度发布、蓝绿部署、金丝雀都是啥?
在滚动部署中,应用的新版本逐步替换旧版本。实际的部署发生在一段时间内。在此期间,新旧版本会共存,而不会影响功能和用户体验。这个过程可以更轻易的回滚和旧组件不兼容的任何新组件。
灰度发布、蓝绿部署、金丝雀都是啥?
|
SQL 数据管理 数据库
DROP 和 TRUNCATE 命令的详细区别
【8月更文挑战第31天】
1717 0
|
存储 SQL 数据库
MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数
MySQL设计规约问题之为何推荐用DECIMAL代替FLOAT和DOUBLE来存储精确浮点数