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

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

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


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


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



相关文章
|
2月前
|
消息中间件 存储 分布式计算
分布式系统的演进过程
【10月更文挑战第24天】总的来说,分布式系统的演进是一个不断适应变化、解决问题和创新发展的过程。从早期的萌芽到如今的多元化发展,它见证了技术的进步和应用场景的拓展。在未来,分布式系统将继续在各个领域发挥重要作用,推动着数字化世界的不断前行。
|
2月前
|
安全 数据管理 测试技术
分布式系统的演进对软件开发的影响
【10月更文挑战第24天】总的来说,分布式系统的演进对软件开发产生了多方面的影响,既带来了挑战,也提供了机遇。开发人员需要不断适应这些变化,提升自身的能力和素质,以更好地应对分布式系统开发带来的各种问题。
44 3
|
7月前
|
缓存 运维 负载均衡
分布式系统架构设计与挑战
【6月更文挑战第29天】分布式系统架构设计涉及组件化、通信、数据一致性、负载均衡和容错处理,旨在实现高可用性和可扩展性。然而,数据一致性、性能、可伸缩性和容错是主要挑战。解决方案包括使用一致性算法、性能优化、设计可伸缩架构和实施容错机制。随着技术进步,这类系统将继续在云、大数据和物联网中扮演关键角色。
|
消息中间件 人工智能 缓存
业务实现真的会因为分布式系统而变得简单么?
在当前互联网技术不断发展的时代,分布式系统成为了许多企业业务中不可或缺的一部分。分布式的出现,一方面提高了系统的可靠性和性能,另一方面也提高了系统的可扩展性和灵活性,这也让分布式系统被广泛应用于各种业务场景中,例如电商、金融、物流等领域。再结合阅读了《聊一聊分布式系统中的时空观构建》这篇文章,更进一步了解分布式系统的空间观构建,通过生活中的时间观念、事情的因果顺序、逻辑时钟等方面让业务实际因为分布式系统变得简化,而更易实现。但是实际的业务实现真的会因为分布式系统而变得更简单么?本文就来简单的聊一下。
85 1
业务实现真的会因为分布式系统而变得简单么?
|
8月前
|
消息中间件 大数据 分布式数据库
分布式事务:构建可靠分布式系统的基石
【4月更文挑战第21天】分布式事务是确保现代分布式系统数据一致性和完整性的关键技术,涉及多服务协调,面临网络延迟、故障和数据一致性等问题。本文探讨了分布式事务的原理,包括两阶段提交、三阶段提交、分布式锁和补偿机制等解决方案,并阐述其在微服务、分布式数据库和消息队列等场景的应用。面对挑战,我们需要持续优化分布式事务处理机制。
|
存储 负载均衡 算法
【系统架构】分布式系统架构设计
【系统架构】分布式系统架构设计
587 0
|
负载均衡 Kubernetes 算法
【韧性架构设计】分布式系统的韧性
【韧性架构设计】分布式系统的韧性
|
存储 运维 监控
蚂蚁超大规模分布式系统稳定性体系实践
大规模分布式系统的稳定性建设,是确保业务服务不受硬件、人为等风险因素影响而中断的核心工作,随着业务规模增大和复杂度的提升,系统稳定性的重要程度和难度也随之增大。在蚂蚁集团业务发展过程中,业务复杂度、用户规模以及业务重要性都逐步增大,相应的稳定性建设也伴随着业务的发展进行了不断地建设和提升。
2205 1
蚂蚁超大规模分布式系统稳定性体系实践
|
运维 算法 网络协议
分布式系统中只有两个难题(下)
分布式系统中只有两个难题(下)
298 0
分布式系统中只有两个难题(下)
|
存储 缓存 cobar
分布式系统设计实践
分布式系统设计实践
266 0