从0开始学架构 - 复杂度来源:高可用

维基百科高可用的定义:

系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。

这个定义的关键在于“无中断”,但恰好难点也在“无中断”上面,因为无论是单个硬件还是单个软件,都不可能做到无中断,硬件会出故障,软件会有 BUG;硬件会逐渐老化,软件会越来越复杂和庞大……

系统的高可用本质上都是通过“冗余”来实现高可用。高可用的“冗余”解决方案,单纯从形式上来看,和高性能是一样的,都是通过增加更多机器来达到目的,但其实本质上是有根本区别的:高性能增加机器目的在于“扩展”处理性能;高可用增加机器目的在于“冗余”处理单元。通过冗余增强了可用性,但同时也带来了复杂性。

计算高可用

这里的“计算”指的是业务的逻辑处理。计算有一个特点就是无论在哪台机器上进行计算,同样的算法和输入数据,产出的结果都是一样的,所以将计算从一台机器迁移到另外一台机器,对业务并没有什么影响。

单机变双机架构

单机变双机架构
  • 需要增加一个任务分配器,选择合适的任务分配器也是一件复杂的事情,需要综合考虑性能、成本、可维护性、可用性等各方面因素。

  • 任务分配器和真正的业务服务器之间有连接和交互,需要选择合适的连接方式,并且对连接进行管理。例如,连接建立、连接检测、连接中断后如何处理等。

  • 任务分配器需要增加分配算法。例如,常见的双机算法有主备、主主,主备方案又可以细分为冷备、温备、热备。

高可用集群架构

高可用集群架构

这个高可用集群相比双机来说,分配算法更加复杂,可以是 1 主 3 备、2 主 2 备、3 主 1 备、4 主 0 备,具体应该采用哪种方式,需要结合实际业务需求来分析和判断,并不存在某种算法就一定优于另外的算法。例如,ZooKeeper 采用的就是 1 主多备,而 Memcached 采用的就是全主 0 备。

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件。
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态 Web 应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。

存储高可用

对于需要存储数据的系统来说,整个系统的高可用设计关键点和难点就在于“存储高可用”。存储与计算相比,有一个本质上的区别:将数据从一台机器搬到到另一台机器,需要经过线路进行传输。线路传输的速度是毫秒级别,同一机房内部能够做到几毫秒;分布在不同地方的机房,传输耗时需要几十甚至上百毫秒。例如,从广州机房到北京机房,稳定情况下 ping 延时大约是 50ms,不稳定情况下可能达到 1s 甚至更多。

虽然毫秒对于人来说几乎没有什么感觉,但是对于高可用系统来说,就是本质上的不同,这意味着整个系统在某个时间点上,数据肯定是不一致的。按照“数据 + 逻辑 = 业务”这个公式来套的话,数据不一致,即使逻辑一致,最后的业务表现就不一样了。

除了物理上的传输速度限制,传输线路本身也存在可用性问题,传输线路可能中断、可能拥塞、可能异常(错包、丢包),并且传输线路的故障时间一般都特别长,短的十几分钟,长的几个小时都是可能的。例如,2015 年支付宝因为光缆被挖断,业务影响超过 4 个小时;2016 年中美海底光缆中断 3 小时等。在传输线路中断的情况下,就意味着存储无法进行同步,在这段时间内整个系统的数据是不一致的。

综合分析,无论是正常情况下的传输延迟,还是异常情况下的传输中断,都会导致系统的数据在某个时间点或者时间段是不一致的,而数据的不一致又会导致业务问题;但如果完全不做冗余,系统的整体高可用又无法保证,所以存储高可用的难点不在于如何备份数据,而在于如何减少或者规避数据不一致对业务造成的影响

分布式领域里面有一个著名的 CAP 定理,从理论上论证了存储高可用的复杂度。也就是说,存储高可用不可能同时满足“一致性、可用性、分区容错性”,最多满足其中两个,这就要求我们在做架构设计时结合业务进行取舍。

CAP 定理

在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistence)等同于所有节点访问同一份最新的数据副本。
  • 可用性(Availability)每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据。
  • 分区容错性(Partition tolerance)以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

根据定理,分布式系统只能满足三项中的两项而不可能满足全部三项。理解 CAP 理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了 C 性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了 A 性质。除非两个节点可以互相通信,才能既保证 C 又保证 A,这又会导致丧失 P 性质。

高可用状态决策

无论是计算高可用还是存储高可用,其基础都是“状态决策”,即系统需要能够判断当前的状态是正常还是异常,如果出现了异常就要采取行动来保证高可用。如果状态决策本身都是有错误或者有偏差的,那么后续的任何行动和处理无论多么完美也都没有意义和价值。但在具体实践的过程中,恰好存在一个本质的矛盾:通过冗余来实现的高可用系统,状态决策本质上就不可能做到完全正确。下面我基于几种常见的决策方式进行详细分析。

独裁式

独裁式决策指的是存在一个独立的决策主体,我们姑且称它为“决策者”,负责收集信息然后进行决策;所有冗余的个体,我们姑且称它为“上报者”,都将状态信息发送给决策者。

独裁式的决策方式不会出现决策混乱的问题,因为只有一个决策者,但问题也正是在于只有一个决策者。当决策者本身故障时,整个系统就无法实现准确的状态决策。如果决策者本身又做一套状态决策,那就陷入一个递归的死循环了。

协商式

协商式决策指的是两个独立的个体通过交流信息,然后根据规则进行决策,最常用的协商式决策就是主备决策

这个架构的基本协商规则可以设计成:

  • 2 台服务器启动时都是备机。
  • 2 台服务器建立连接。
  • 2 台服务器交换状态信息。
  • 某 1 台服务器做出决策,成为主机;另一台服务器继续保持备机身份。

协商式决策的架构不复杂,规则也不复杂,其难点在于,如果两者的信息交换出现问题(比如主备连接中断),此时状态决策应该怎么做。

  • 如果备机在连接中断的情况下认为主机故障,那么备机需要升级为主机,但实际上此时主机并没有故障,那么系统就出现了两个主机,这与设计初衷(1 主 1 备)是不符合的。
  • 如果备机在连接中断的情况下不认为主机故障,则此时如果主机真的发生故障,那么系统就没有主机了,这同样与设计初衷(1 主 1 备)是不符合的。
  • 如果为了规避连接中断对状态决策带来的影响,可以增加更多的连接。例如,双连接、三连接。这样虽然能够降低连接中断对状态带来的影响(注意:只能降低,不能彻底解决),但同时又引入了这几条连接之间信息取舍的问题,即如果不同连接传递的信息不同,应该以哪个连接为准?实际上这也是一个无解的答案,无论以哪个连接为准,在特定场景下都可能存在问题。

综合分析,协商式状态决策在某些场景总是存在一些问题的。

民主式

民主式决策指的是多个独立的个体通过投票的方式来进行状态决策。例如,ZooKeeper 集群在选举 leader 时就是采用这种方式。

民主式决策和协商式决策比较类似,其基础都是独立的个体之间交换信息,每个个体做出自己的决策,然后按照“多数取胜”的规则来确定最终的状态。不同点在于民主式决策比协商式决策要复杂得多,ZooKeeper 的选举算法 Paxos,绝大部分人都看得云里雾里,更不用说用代码来实现这套算法了。

除了算法复杂,民主式决策还有一个固有的缺陷:脑裂。这个词来源于医学,指人体左右大脑半球的连接被切断后,左右脑因为无法交换信息,导致各自做出决策,然后身体受到两个大脑分别控制,会做出各种奇怪的动作。例如:当一个脑裂患者更衣时,他有时会一只手将裤子拉起,另一只手却将裤子往下脱。脑裂的根本原因是,原来统一的集群因为连接中断,造成了两个独立分隔的子集群,每个子集群单独进行选举,于是选出了 2 个主机,相当于人体有两个大脑了。

从图中可以看到,正常状态的时候,节点 5 作为主节点,其他节点作为备节点;当连接发生故障时,节点 1、节点 2、节点 3 形成了一个子集群,节点 4、节点 5 形成了另外一个子集群,这两个子集群的连接已经中断,无法进行信息交换。按照民主决策的规则和算法,两个子集群分别选出了节点 2 和节点 5 作为主节点,此时整个系统就出现了两个主节点。这个状态违背了系统设计的初衷,两个主节点会各自做出自己的决策,整个系统的状态就混乱了。

为了解决脑裂问题,民主式决策的系统一般都采用“投票节点数必须超过系统总节点数一半”规则来处理。如图中那种情况,节点 4 和节点 5 形成的子集群总节点数只有 2 个,没有达到总节点数 5 个的一半,因此这个子集群不会进行选举。这种方式虽然解决了脑裂问题,但同时降低了系统整体的可用性,即如果系统不是因为脑裂问题导致投票节点数过少,而真的是因为节点故障(例如,节点 1、节点 2、节点 3 真的发生了故障),此时系统也不会选出主节点,整个系统就相当于宕机了,尽管此时还有节点 4 和节点 5 是正常的。

综合分析,无论采取什么样的方案,状态决策都不可能做到任何场景下都没有问题,但完全不做高可用方案又会产生更大的问题,如何选取适合系统的高可用方案,也是一个复杂的分析、判断和选择的过程。

本节总结

高可用与高性能,是架构设计中两个非常重要的决策因素。因此,面对不同业务系统的不同需求,对高可用与高性能也会有不同的决策结论,其实现的复杂度也各不相同。支付宝业务,对于可用性和性能就会有很高的要求,在可用性方面希望能提供 7*24 不间断服务,在高性能方面则希望能实时收付款;而对于一个学生管理系统,在可用性与性能方面就不一定要有多高的要求,比如晚上可关机,几秒内能查询到信息也可接受。为此,高可用性与高性能的复杂度讨论需要结合业务需求。

什么是可用性

定义可用性,可以先定义什么是不可用。需要经历若干环节,网站的页面才能呈现在最终的用户面前;而其中的任何一个环节出现了故障,都可能会导致网站的页面不可访问,也就是出现了网站不可用的情况。昨夜 iOS 版本 QQ 出现大面积闪退就是一个系统不可用的典型案例。

我们可以利用百分比来对网站可用性进行度量:

  • 网站不可用时间 = 完成故障修复的时间点 - 故障发现的时间点
  • 网站年度可用时间 = 年度总时间 - 网站不可用时间
  • 网站年度可用性 = (网站年度可用时间 / 年度总时间) x 100%

举例:一些知名大型网站的可用性可达到 99.99%(俗称 4 个 9),我们可以算一下一年下来留给处理故障的时间有多少?

年度总时间 = 365 \* 24 \* 60 = 525600 分钟
网站不可用时间 = 525600 \* (1 - 99.99%) = 52.56 分钟

也就是,如果网站要达到 4 个 9 的可用性,一年下来网站不可用时间最多 53 分钟(也就是不足 1 个小时)。

可见,高可用性就是技术实力的象征,高可用性就是竞争力。

为什么会出现不可用

硬件故障。网站多运行在普通的商用服务器,而这些服务器本身就不具备高可用性,再加之网站系统背后有数量众多服务器,那么一定时间内服务器宕机是大概率事件,直接导致部署在该服务器上的服务受影响。

软件 BUG 或网站更新升级发布。BUG 不能消灭,只能减少;上线后的系统在运行过程中,难免会出现故障,而这些故障同样直接导致某些网站服务不可用;此外,网站更新升级发布也会引起相对较频繁的服务器宕机。

不可抗拒力。如地震、水灾、战争等。

如何做到高可用

核心思想:网站高可用的主要技术手段是服务与数据的冗余备份与失效转移。同一服务组件部署在多台服务器上;数据存储在多台服务器上互相备份。通过上述技术手段,当任何一台服务器宕机或出现各种不可预期的问题时,就将相应的服务切换到其他可用的服务器上,不影响系统的整体可用性,也不会导致数据丢失。

从架构角度看可用性:当前网站系统多采用经典的分层模型,从上到下为:应用层、服务层与数据层。应用层主要实现业务逻辑处理;服务层提供可复用的服务;数据层负责数据读写;在部署架构上常采用应用和数据分离部署,应用会部署到不同服务器上,这些服务器被称为应用层的服务器;这些可复用的服务也会各自部署在不同服务器上,称为服务层的服务器;而各类数据库系统、文件柜等数据则部署在数据层的服务器。

硬件故障方面引起不可用的技术解决措施

  • 应用服务器。可通过负载均衡设备将多个应用服务器构建为集群对外提供服务(前提是这些服务需要设计为无状态,即应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行业务逻辑的操作响应),当均衡设备通过心跳检测手段检测到应用服务器不可用时,则将其从集群中移除,并将请求切换到其他可用的应用服务上。
  • 服务层服务器。这些服务器被应用层通过分布式服务框架(如Dubbo)访问,分布式服务框架可在应用层客户端程序中实现软件负载均衡,并通过服务注册中心提供服务的服务器进行心跳检测,当发现有服务器不可用时,立即通知客户端程序修改服务列表,同时移除响应的服务器。
  • 数据服务器。需要在数据写入时进行数据同步复制,将数据写入多台服务器上,实现数据冗余备份;当数据服务器宕机时,应用程序将访问切换到有备份数据的服务器上。

软件方面引起不可用的技术解决措施

  • 通过软件开发过程进行质量保证。
  • 通过预发布验证、严格测试、灰度发布等手段,尽量减少上线服务的故障。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容

  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,750评论 0 5
  • 网站的可用性强调的是对最终用户的使用价值。它牵动着人们的神经,直接影响着公司的形象和利益,许多互联网公司都将网站的...
    deniro阅读 3,586评论 0 18
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • 一、 设计理念 1.空间换时间 1)多级缓存,静态化 客户端页面缓存(http header中包含Expires/...
    零一间阅读 1,574评论 0 13
  • 我有两个最好的朋友,她们们俩个是我在学校最要好的朋友。 一个是自己班的李美丹,一个是六四班的...
    Lcr_阅读 374评论 0 0