- 分布式系统实际上就是研究如何协调这些联网的计算机来共同完成任务
- 分布式系统中一般是多进程并发运行
- 不共享OS, 通过网络通信来协作通信
- 不共享时钟, 很难使用时间来定义两个事件的先后顺序
那为什么需要分布式系统?
- 高性能:由于单一计算机硬件的物理限制和摩尔定律的失效。现代解决方案是通过多核CPU或将多台计算机组合成分布式系统来获得高性能。
- 可扩展性:单台计算机有其扩展限制,分布式存储系统能够满足大规模的需求,尤其是数据密集型应用程序的需求。
- 高可用性:为了满足近乎全天候的在线服务要求,分布式系统通过数据和计算的冗余来实现高度的可用性。
- 必要性:某些应用,如跨银行转账,由于其天然的需求和一致性要求,必须采用分布式系统。
而在分布式系统中,有如下几大谬误:
- 网络是可靠的
- 延迟为零
- 带宽是无限的
- 网络是安全的
- 拓扑结构不会改变
后续的文章会重点讨论前面2点。我们将这两个问题归为 网络延迟问题 。除此之外,还有两个分布式系统中很常见的问题,部分失效问题和时钟问题。
下面来讨论一下上述这些基本问题出现的特点。
在分布式系统的消息传递中时刻都有可能出现以下问题:
- 消息丢失:真的丢失了
- 消息延迟:实际消息并未丢失,只是到达时间被延迟
- 消息重复:由于网络重传,可能会收到同一消息多次
- 误判服务状态:因消息延迟,可能误认为服务已故障或下线,但实际上服务仍在运行
- 消息顺序:消息可能乱序到达,或在不同节点上的到达顺序有异。
尽管TCP等高级协议为开发者提供了"网络可靠"的错觉,但实际上,网络仍基于可能故障的硬件,因此设计分布式系统时需要考虑这些不确定性因素。
我们平时都在单机系统中工作,程序运行要么正常工作,要么彻底出错。
但是在分布式系统中,系统时常会出现某些节点停止运行,而其他节点是正常工作的,但由于网络中断导致无法协同工作;系统中某些节点也可能以某种不可预知的方式宕机。这就是 "部分失效"。
所以在分布式系统工作过程中,节点有可能能工作,有可能不能工作;有时甚至不知道应用程序是否成功了,因为消息通过网络传播的时间也是不确定的。
那么对应到单机系统,涉及多个节点工作的分布式系统很难追求原子性。在这种情况下,部分失效就 会带来很大的复杂性和挑战,甚至严重影响系统的性能。
在单机系统中,每个进程都有一个共同的时间,可以通过这个时间来调度进程从而表现出同步行为。
而在分布式系统中,每台机器都有自己的时钟,各个物理设备的本地时钟走时并不准确,可能比其他机器稍快或更慢。
另外消息在节点间的传输也需要时间,但是这个延迟也是不定的,我们基本上无法得知消息传递到底花了多久。这也让我们很难确定在涉及多台机器时事件发生的顺序。
先通过分布式系统的几个关键属性来定义系统模型,再来学习其他的架构模型。从分布式系统中的两个经典思想实验开始:两将军问题和拜占庭将军问题。
军队A | 军队B | 结果 |
---|---|---|
不进攻 | 不进攻 | 无事发生 |
不进攻 | 进攻 | B战败 |
进攻 | 不进攻 | A战败 |
进攻 | 进攻 | 城市占领 |
所以可见两边必须通过一个信使沟通并约定攻击时间,两方都确保对方得知自己的攻击计划。如果消息丢失,两边就无法达成共识。
两将军问题虽然已被证明无解,但计算机科学家们仍然找到了工程上的解决方案,我们熟 悉的传输控制协议 (TCP) 的“三次握手”就是两将军问题的一个工程解。
这个思想实验还表明,在一个分布式系统中,一个节点没有办法确认另一个节点的状态,一个节点想要知道某个节点的状态的唯一方法是通过发送信息进行交流来尽量得知。
拜占庭将军和两将军问题类似,只是将两将军问题扩展为三支军队。拜占庭将军问题的挑战在于,将军中可能出现叛徒。在最坏的情况下,背叛的将领可能串通起来,选择性地发送投票信息,破坏整个军事行动。 而拜占庭将军问题就是要确保所有忠实的将领在同一个计划上达成共识(无论进攻还是撤退)。 我们不需要指定叛变的将领做什么,我们只能让忠诚的将领们达成共识。