zoukankan      html  css  js  c++  java
  • 第八章

    第八章 分布式系统的挑战

    故障与部分失效

    单台节点上的软件通常不应该出现模棱两可的现象:当硬件正常工作时,相同的操作通常总会产生相同的结果(即确定性),在单节点上一个质量合格的软件状态要么是功能正常,要么是完全失效,而不会介于两者之间。
    在分布式系统中,可能会出现系统的一部分工作正常,但其他某些部分出现难以预测的故障,我们称之为“部分失效”。

    云计算和超算

    关于如何构建大规模计算系统有以下几种不同的思路:

    • 规模的一个极端是高性能计算
    • 另一个极端是云计算
    • 传统企业数据中心则位于以上两个极端之间。

    对于高性能计算,通常会定期对任务状态进行快照,然后保存在持久存储上,当某节点出现故障,解决方案是简单地停止整个集群的任务;等故障节点修复之后,从最近的快照检查点继续执行
    本书的重点是基于互联网的服务系统:

    • 许多互联网服务都是在线的,需要随时为用户提供低延迟服务
    • 云计算在大规模部署时成本更低
    • 大型数据中心网络通常基于IP和以太网,高性能计算则通常特定的网络拓扑结构
    • 系统越大,其中局部组件失效的概率就越大。
    • 如果系统可以容忍某些失败的节点,而使整体继续工作,则对系统运维帮助极大
    • 对于全球分散部署的多数据中心(使用户访问地理靠近的数据中心,从而降低延迟),通信很可能经由广域网,与本地网络相比,速度更慢且更加不可靠。

    要使分布式系统可靠工作,就必然面临部分失效,这就需要依靠软件系统来提供容错机制。

    不可靠的网络

    无共享并不是构建集群系统的唯一方式 ,但它却是构建互联网服务的主流方式。主要是由于以下几个原因:由于不需要专门的硬件因此成本相对低廉,可以采用通用的商品化硬件,可以采用跨区域的多数据中 心来实现高可靠性。
    发送者不清楚数据包是否完成了发送,只能选择让接收者来回复响应消息,但回复也有可能丢失或延迟。
    处理这个问题通常采用超时机制:在等待一段时间之后,如果仍然没有收到回复则选择放弃,并且认为响应不会到达。

    现实中的网络故障

    一些系统研究和大量的侧面证据表明,网络问题出人意料地普遍,增加元余网络设备并不会像期望的那样可以显著减少故障,主要是因为无法有效防范人为错误。
    如果没有处理或者测试网络故障,可能会发生意想不到的后果。我们推荐有计划地人为触发网络问题,目的是测试系统的反应情况。

    检测故障

    许多系统都需要自动检测节点失效这样的功能。负载均衡器需要避免向已失效的节点继续分发请求,对于主从复制的分布式数据库,如果主节点失败,需要将某个从节点提升为主节点。由于网络的不确定性使得判断节点是否失效非常困难。

    超时与无限期的延迟

    如果超时是故障检测唯一可行的方位, 那么超时应该设多长呢?
    设置较长的超时值意味着更长时间的等待,才能宣告节点失效,较短的超时设置可以帮助快速检测故障,但可能会出现误判。
    当一个节点被宣告为失效,其承担的责任要交给其他节点,这个过程困难会给其他节点以及网络带来额外负担,可能导致失效扩散。
    异步网络理论上的延迟无限大,多数服务端也无法保证在给定的某个时间内一定完成请求处理。如果超时设置太小,只需要一个短暂的网络延迟尖峰就会导致包超时进而将系统标记为失效。

    网络拥塞与排队

    计算机网络上数据包延的变化根源往往在于排队:网络交换机中,操作系统中,虚拟机管理器排队缓冲中,TCP流量控制时等等。所有以上因素都会造成网络延迟的变化或者不确定性。
    网络延迟通常会波动很大,只能通过实验方式一步步设置超时。更好的做法是超时设置为一个变量,持续测量响应时间及其变化,然后根据最新的响应时间分布来自动调整。目前TCP超时重传也采用了类似的机制。

    同步与异步网络

    统的固定电话网络非常可靠,语音延迟和掉话现象极为罕见,这样的固定电话网络需要有持续端到端的低延迟和足够的带宽来传输音频数据。
    这种网络本质是同步的 : 即使数据中间经过了多个路由器,16bit空间在电路建立时已经在网络中得到预留,不会受到排队的影响。由于没有排队,网络最大的端到端延迟是固定的。我们称之为有界延迟。

    网络延迟是否可预测

    电路非常适合音频或视频通话,通话期间只需每秒传送固定数量的数据。但对于访问网页,发送电子邮件或传输文件等无撞事先确定带宽需求,我们只是希望它尽快完成。
    如果你想通过电路链接来传输文件,将不得不预估一个待分配的带宽。 如果预估值太低,传输速度就特别缓慢,甚至无法实际可用;如果预估带宽太高,电路甚至由于没有足够的带宽而无法完成建立。
    因此对于突发数据的传输,电路网络无法充分利用网络容量,导致发送缓慢,相比之下TCP动态调整传输速率则可以充分利用所有可用的网络容量。
    也曾有一些尝试建立支持电路交换和分组交换的混合网络,它在链路层实现端到端的流量控制,最终可以在分组网络上模拟电路交换,或者说提供统计意义上的有限延迟。但是,目前此类QoS在多租户数据中心、公有云和广域网中并未启用。

    不可靠的时钟

    网络上的每台机器都有自己的时钟硬件设备,通常是石英晶体振荡器 。这些设备并非绝对准确,即每台机器都维护自己本地的时间版本,可能比其他机器稍快或更慢。
    可以在一定程度上同步机器之间的时钟,最常用的方也是网络时间协议(NTP),它可以根据一组专门的时间服务器来调整本地时间,时间服务器则从精确更高的时间源(如 GPS接收机) 获取高精度时间 。

    单调时钟与墙上时钟

    现代计算机内部至少有两种不同的时钟 : 一个是墙上时钟 (或称钟表时间), 一个是单调时钟。

    墙上时钟

    墙上时钟根据某个日历(也称为墙上时间)返回当前的日期与时间。
    墙上时钟可以与NTP同步。但是如果本地时钟远远快于NTP服务器,强行重置之后会跳回到先前的某个时间点。这种跳跃以及经常忽略闰秒 ,导致其不太适合测量时间间隔。

    单调时钟

    单调时钟更适合测量:持续时间段(时间间隔),单调时钟的名字来源于它们保证总是向前(而不会出现墙上时钟的回拨现象)。注意单调时钟的绝对值井没有任何意义
    如果服务器有多路CPU ,则每个CPU可能有单独的计时器,操作系统会补偿多个计时器之间的偏差, 从而为应用层提供统一的单调递增计时。
    如果NTP检测到本地石英比时间服务器上更快或者更慢, NTP会调整本地石英的震动频率(这被称为摆动)
    在分布式系统中,可以采用单调时钟测量一段任务的持续时间(例如超时 ),它不假定节点间有任何的时钟同步,且可以容忍轻微测量误差。

    时钟同步与准确性

    单调时钟不需要同步,但是墙上时钟需要根据NTP服务器或其他外部时间惊做必要的调整 。

    • 计算机中的石英钟不够精确,存在漂移现象(运行速度会加快或减慢)。
    • 如果时钟与NTP服务器的时钟差别太大,可能会出现拒绝同步,或者本地时钟将被强制重置。在重置前后应用程序观察可能会看到时间突然倒退或突然跳跃的现象。
    • 如果与NTP服务器链接失败(如防火墙),可能会很长一段时间没有留意到错误配置最终导致同步失败。
    • NTP同步会受限于 当 时的网络环境特别是延迟,如果网 络拥塞、数据包延迟变化不定, 则NTP 同步的准确性会受影响。
    • 一些NTP服务器本身出现故障、或者配置错误 ,其报告的时间可能存在数小时的偏差
    • 闰秒会产生一分钟为59秒或61秒的现象,这会在使一些对闰秒毫无防范的系统出现混乱
    • 在虚拟机中,由于硬件时钟也是被虚拟化的,这对于需要精确计时的应用程序提出了额外的挑战
    • 如果运行在未完全可控的设备上,需要留意不能完全相信设备上的硬件时钟。

    如果确实需要投入大量资橱,是可以达到非常高的时钟精度。高精度的时钟可以采用 GPS接收机,精确时间协议( PTP) 并辅以细致的部署和监测。

    依赖同步的时钟

    如果应用需要精确同步的时钟,最好仔细监控所有节点上的时钟偏差。如果某个节点的时钟漂移超出上限, 应将其宣告为失效,并从集群中移除。这样的监控的目的是确保在造成重大影响之前尽早发现并处理问题。

    时间戳与事件顺序

    对于一个常见的功能 : 跨节点的事件排序,如果它高度依赖时钟计时·,就存在一定的技术风险。

    • 数据库写入可能会奇怪地丢失,后续发生的写操作却没法覆盖另一个较早的值,原因是后者节点的时钟太快了
    • 最后写入者获胜(LWW)无法区分连续快速发生的连续写操作和并发写入。
    • 由于时钟精读的限制(例如毫秒级),两个节点可能各自独立产生了完全相同的时间戳。

    “最新”的定义如果取决于墙上时钟就会引入偏差,即使采用了NTP同步时钟,依然可能会出现。除了石英漂移等误差来源之外, NTP同步精度本身要受限于所在的网络延迟。要达到正确的排序, 需要时钟拥精度要远远高于被测量的对象。
    对于排序来说,基于递增计数器而不是振荡石英晶体的逻辑时钟是更可靠的方式。
    逻辑时钟并不测量一天 的某个时间点或时间间隔,而是事件的相对顺序(事件发生的相对前后关系)。与之对应的,墙上时钟和单调时钟都属于物理时钟。

    时钟的置信区间

    使用本地网络和公共互联网上的NTP服务器都无法保证墙上时钟的精度,因此我们不应该将时钟读数视为一个精确的时间点,而更应该视为带有置信区间的时间范围。
    可以根据具体的时间拥来推算出时钟误差的上限:

    • 如果节点上直接装有GPS接收器或原子(铯)时钟,那它的误差范围通常可查询制造商的手册 。
    • 如果节点是从服务器获取时间,贝 lj不确定性取决于上次服务器同步以来的石英漂移范围,加上NTP服务器的不确定性,再加上与服务器之间的网络往返时间

    全局快照的同步时钟

    当数据库分布在多台机器上时,由于需要复杂的协调以产生全局的、单i周递增的事务ID(跨所有分区)。但在分布式系统中创建事务ID通常会引入瓶颈。
    Google Spanner根据时钟置信区间,如果A区间最早值晚于B区间最晚值,则可以断定B区间一定发生在区间之后。如果发生了重叠则无法判断。

    进程暂停

    从节点如何确信主节点没有被宣告失效?一种思路是主节点从其他节点获得一个租约,类似一个带有超时的锁。节点在租约有效时间内维持主节点身份,并在到期之前定期更新租约,如果节点发生故障,则租约到期后另一个节点可以接管。
    但这依赖于同步时钟,但如果进程暂停,则时间就会计算错误。很多情况下进程会暂停,例如:编程语言进行垃圾回收GC时,虚拟机暂停,电脑休眠,虚拟机切换,磁盘同步,虚拟内存缺页中断,通过发送SIGSTOP信号来暂停UNIX进程等等。
    分布式系统中的一个节点必须假定,执行过程中的任何时刻都可能被暂停相当长一段时间,包括运行在某个函数中间 。

    响应时间保证

    有些软件在指定时间内无法响应则会导致严重后果,这就是所谓的硬实时系统。
    提供实时保证需要来自软件枝的多个层面的支持:首先是一个实时操作系统保证进程在给定的间隔内完成CPU时间片的调度分配:其次,库函数也必须考虑最坏的执行时间;然后,动态内存分配很可能要受限或者完全被禁止,最终还是需要大量、充分的测试和验证,以确保满足要求 。

    调整垃圾回收的影响

    有些措施虽然井不能完全避免垃圾回收导致的进程暂停,但可以有效地减少对应用层的影响。

    • 把GC暂停视为节点的一个计划内的临时离线,当节点启动垃圾回收时,通知其他节点来接管客户端的请求。
    • 只对短期对象(可以快速回收)执行垃圾回收,然后在其变成长期存活对象之 前, 采取定期重启 的策略从而避免对长期存活对象执行全面回收

    知识、真相与谎言

    如果远程节点没有响应,由于没能区分网络本身的问题还是节点的问题,就无从知道节点究竟处于什么状态。

    真相由多数决定

    节点不能根据自己的信息来判断自身的状态。由于节点可能随时会失效,可能会暂停-假死,甚至最终无法恢复 ,因此,分布式系统不能完全依赖于单个节点。
    目前,许多分布式算怯都依靠告定票数 ,即在节点之间进行投票,任何决策都需要来自多个节点的最小投票数,从而少对特定节点的依赖。最常见的怯定票数是取系统节点半数以上。

    主节点与锁

    如果主节点已经更换,而原主节点并不知道继续进行其工作,可能会导致出现问题

    Fencing令牌

    当使用锁和租约来保护资源的并发访问时,必须保证过期的主节点不能影响其他正常部分。实现这一目标可以采用fencing(栅栏)。
    客户端获得锁租约时还会获得令牌号,令牌每授予一次就会递增,客户端每次向存储服务器发送写请求时都必须包含所持有的的fencing令牌,如果存储服务器收到了更低版本的令牌号,就会拒绝写请求。
    客户端如果发现处理过更高令牌的请求,也会拒绝持有低令牌的写请求。

    拜占庭故障

    如果节点试图破坏系统,则可能在发消息时伪造令牌,例如节点明明没有收到某条消息,但却对外声称收到了,这种行为成为拜占庭故障,在这样不信任的环境中需要达成共识的问题也被称为拜占庭将军问题。
    如果某个系统中即使发生部分节点故障,甚至不遵从协议,或者恶意攻击、干扰网络,但仍可继续正常运行,那么我们称之为拜占庭式容错系统
    web应用程序可能会发送带有恶意行为的请求,因此需要输入验证,安全监测,输出转义等,DNA并不常使用拜占庭容错协议,而是让服务器全权决定,只有在没有中央决策机制的点对点网络中,拜占庭容错才更为必要。
    软件中的 bug可以被认为是拜占庭式故障,但如果将相同的软件部署到所有节点上,那么即使拜占庭式的容错算法也无曲解决问题。
    传统的安全措施如认证、访问控制、加密、防火墙等 ,仍是防范攻击的主要保护机制。

    弱的谎言形式

    推荐增加必要的机制来防范一些不那么恶意的“谎言”,可以帮助提高软件系统的可靠性和健壮性 。

    • 由于硬件问题或操作系统、驱动程序 、路由器等方面的错误,导致网 络数据包有时出现损坏,可以在应用层添加校验和。
    • 对公众开放的应用必须仔细检查用户的所有输入
    • NTP客户端最好配置多个时间服务器。

    理论系统模型与现实

    通过定义一些系统模型来形式化描述算陆的前提条件:

    • 同步模型:同步模型假定有上界的网络延迟,有上界的进程暂停和有上界的时钟误差。
    • 部分同步模型:部分同步意味着系统在大多数情况下像一个同步系统一样运行,但有时候会超出网络延迟,进程暂停和时钟襟移的预期上界
    • 异步模型:一个算惶不会对时机做任何的假设,甚至里面根本没有时钟

    三种最常见的节点失效系统模型:

    • 崩溃-中止模型:这意味着节点可能在任何时候突然停止响应,且该节点以后永远消失,无法恢复。
    • 崩溃-恢复模型:节点可能会在任何时候发生崩溃,且可能会在一段时间后得到恢复并再次响应。
    • 拜占庭失效模型:节点可能发生任何事情,包括试图作弊和欺骗其他节点。

    算法的正确性

    我们可以通过描述目标分布式算法的相关属性来定义其正确性。
    例如对于锁服务的fencing令牌生成算法,要求算法具有以下属性:

    • 唯一性
    • 单调递增
    • 可用性

    安全性与活性

    安全性通常可以理解为“没有发生意外”,而活性则类似“预期的事情最终一定会发生”。

    • 如果违反了安全属性,我们可以明确指向发生的特定的时间点,且一旦违反安全属性,违规行为无战f的销,破坏已实际发生。
    • 活性则 反过来:可能无陆明确某个具体的时间点,但总是希望在未来某个时间点可以满足要求。

    通常对于分布式算毡,要求在所有可能的系统模型下,都必须符合安全属性,而对于活性,则存在一些必要条件。

    将系统模型映射到现实世界

    抽象的系统模型把实际系统中的复杂性提炼成一个更容易理解、更具可控性的抽象错误集合,可以有效帮助我们理解问题之本质,然后设计系统性方法来最终解决问题。

  • 相关阅读:
    CodeForces 734F Anton and School
    CodeForces 733F Drivers Dissatisfaction
    CodeForces 733C Epidemic in Monstropolis
    ZOJ 3498 Javabeans
    ZOJ 3497 Mistwald
    ZOJ 3495 Lego Bricks
    CodeForces 732F Tourist Reform
    CodeForces 732E Sockets
    CodeForces 731E Funny Game
    CodeForces 731D 80-th Level Archeology
  • 原文地址:https://www.cnblogs.com/aojun/p/15269118.html
Copyright © 2011-2022 走看看