故障与部分失效
单机上的软件比较稳定,要么功能完好,要么整个系统故障,而不是介于两者之间。分布式系统中,尽管系统的其他部分工作正常,但系统的某些部分可能会以某种不可预知的方式被破坏。这被称为部分失效(partial failure)。难点在于部分失效是不确定性的(nonderterministic)。
云计算与超级计算机
构建分布式系统的思路?接受部分故障的可能性,并在软件中建立容错机制。
不可靠的网络
如果发送请求并没有得到响应,则无法区分(a)请求是否丢失,(b)远程节点是否关闭,或(c)响应是否丢失。怎么处理网络错误?
● 通常方法是超时(Timeout):在一段时间之后放弃等待,并且认为响应不会到达。
● 但是,当发生超时时,你仍然不知道远程节点是否收到了请求(如果请求仍然在某个地方排队,那么即使发送者已经放弃了该请求,仍然可能会将其发送给接收者)。
真实世界的网络故障
检测故障
超时与无穷的延迟
网络拥塞和排队
怎么解决多租户数据中心的网络拥塞问题?
● 原因:在公共云和多租户数据中心中,资源被许多客户共享:网络链接和交换机,甚至每个机器的网卡和CPU(在虚拟机上运行时)。
● 解决办法:通过实验方式选择超时:在一段较长的时期内、在多台机器上测量网络往返时间的分布,以确定延迟的预期变化。然后,考虑到应用程序的特性,可以确定故障检测延迟与过早超时风险之间的适当折衷。
● 更好的办法:不是固定的常量超时时间,而是连续测量响应时间及其变化来自动调整超时时间。
同步网络与异步网络
不可靠的时钟
时钟和时间很重要。应用程序以各种方式依赖于时钟来回答以下问题:
- 这个请求是否超时了?
- 这项服务的第99百分位响应时间是多少?
- 在过去五分钟内,该服务平均每秒处理多少个查询?
- 用户在我们的网站上花了多长时间?
- 这篇文章在何时发布?
- 在什么时间发送提醒邮件?
- 这个缓存条目何时到期?
- 日志文件中此错误消息的时间戳是什么?
时钟为什么不可靠?
● 分布式系统中,时间很棘手,因为通信不是即时的:网络延迟,并且不知道晚了多少时间,导致不知道事件发生的顺序。
● 每个机器都有自己的时钟,是个硬件设备:石英晶体振荡器。但是该硬件不可靠,需要通过服务器进行同步。
单调钟与日历时钟
现代计算机至少有两种不同的时钟:时钟和单调钟。尽管它们都衡量时间,但区分这两者很重要,因为它们有不同的目的。
时钟同步与准确性
依赖同步时钟
进程暂停
知识 真相与谎言
本章到目前为止,我们已经探索了分布式系统与运行在单台计算机上的程序的不同之处:没有共享内存,只有通过可变延迟的不可靠网络传递的消息,系统可能遭受部分失效,不可靠的时钟和处理暂停。 这些系统的讨论与哲学有关:在系统中什么是真什么是假?如果感知和测量的机制都是不可靠的,那么关于这些知识我们又能多么确定呢?软件系统应该遵循我们对物理世界所期望的法则,如因果关系吗?
真理由多数所定义
● 节点不能根据自己的信息来判断自身的状态。
● 因为节点可能随时失效,可能会暂停-假死,可能最终都无法恢复。
● 相反,许多分布式算法都依赖于法定人数,即在节点之间进行投票:决策需要来自多个节点的最小投票数,以减少对于某个特定节点的依赖。
● 个体哪怕没死,当被法定数量的节点宣告死亡时,它也必须被认定为死的。个体必须遵守法定决定并下台。
最常见的法定人数是超过一半的绝对多数(尽管其他类型的法定人数也是可能的)。
第九章将继续讨论共识算法。
领导者和锁
通常情况下,一些东西在一个系统中只能有一个。例如:
- 数据库分区的领导者只能有一个节点,以避免脑裂(split brain)
- 特定资源的锁或对象只允许一个事务/客户端持有,以防同时写入和损坏。
- 一个特定的用户名只能被一个用户所注册,因为用户名必须唯一标识一个用户。
如果持有租约的客户端暂停太久,它的租约将到期。另一个客户端可以获得同一文件的租约,并开始写入文件。当暂停的客户端回来时,它认为(不正确)它仍然有一个有效的租约,并继续写入文件。结果,客户的写入冲突和损坏的文件。
防护令牌
客户端1以33的令牌获得租约,但随后进入一个长时间的停顿并且租约到期。客户端2以34的令牌(该数字总是增加)获取租约,然后将其写入请求发送到存储服务,包括34的令牌。稍后,客户端1恢复生机并将其写入存储服务,包括其令牌值33.但是,存储服务器会记住它已经处理了一个具有更高令牌编号(34)的写入,因此它会拒绝带有令牌33的请求。 如果将ZooKeeper用作锁定服务,则可将事务标识zxid或节点版本cversion用作屏蔽令牌。由于它们保证单调递增,因此它们具有所需的属性
拜占庭故障
当一个系统在部分节点发生故障、不遵守协议、甚至恶意攻击、扰乱网络时仍然能继续正确工作,称之为拜占庭容错(Byzantine fault-tolerant)的,在特定场景下,这种担忧在是有意义的
弱谎言形式
尽管我们假设节点通常是诚实的,但值得向软件中添加防止“撒谎”弱形式的机制——例如,由硬件问题导致的无效消息,软件错误和错误配置。这种保护机制并不是完全的拜占庭容错,因为它们不能抵挡决心坚定的对手,但它们仍然是简单而实用的步骤,以提高可靠性。
系统模型与现实
分布式系统问题要求我们以某种方式将我们期望在系统中发生的错误形式化——模型
安全性和活性
有必要区分两种不同的属性:安全(safety)属性和活性(liveness)属性。
● 刚才的例子中,唯一性和单调序列是安全属性,而可用性是活性属性。
两种性质的通俗理解/区别?
● 思路:活性属性通常在定义中通常包括“最终”一词。 (是的,你猜对了——最终一致性是一个活性属性。)
● 安全通常被非正式地定义为:没有坏事发生
● 活性通常就类似:最终好事发生。
● 最好不要过度阅读非正式的定义,因为好和坏是主观的。
安全和活性的实际定义是精确的和数学的:
● 如果安全属性被违反,我们可以指向一个特定的安全属性被破坏的时间点
○ 例如,如果违反了唯一性属性,我们可以确定重复的防护令牌被返回的特定操作。违反安全属性后,违规行为不能被撤销——损失已经发生。
● 活性属性反过来:在某个时间点(例如,一个节点可能发送了一个请求,但还没有收到响应),它可能不成立,但总是希望在未来能成立(即通过接受答复)。
为什么要区分安全属性和活性属性?
● 可以帮助我们处理困难的系统模型。
● 对于分布式算法,在系统模型的所有可能情况下,要求始终保持安全属性是常见的。
○ 也就是说,即使所有节点崩溃,或者整个网络出现故障,算法仍然必须确保它不会返回错误的结果(即保证安全属性得到满足)。
● 但是,对于活性属性,我们可以提出一些注意事项:
○ 例如,只有在大多数节点没有崩溃的情况下,只有当网络最终从中断中恢复时,我们才可以说请求需要接收响应。
○ 部分同步模型的定义要求系统最终返回到同步状态——即任何网络中断的时间段只会持续一段有限的时间,然后进行修复。
网友评论