1.CAP 理论
CAP定理(CAP theorem)又被称作布鲁尔定理(Brewer's theorem),是回加州大学伯克得分校的计算机科学家埃里克·布鲁尔(Eric Brewer)在2000年的ACM PODC上提出的一个猜想。2002 年,麻省理工学院的赛斯·吉尔伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)发表了布鲁尔猜想的证明,使之成为分布式计算领域公认的一个定理。
第一版解释:简单翻译为:对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三个设计约束。
第二版解释:在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及读写操作时,只能保证一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三者中的两个,另外一个必须被牺牲。
差异点:
• 第二版定义了什么才是 CAP 理论探讨的分布式系统,强调了两点:interconnected 和 share data,为何要强调这两点呢? 因为分布式系统并不一定会互联和共享数据。最简单的例如 Memcache 的集群,相互之间就没有连接和共享数据,因此 Memcache 集群这类分布式系统就不符合 CAP 理论探讨的对象;而 MySQL 集群就是互联和进行数据复制的,因此是 CAP 理论探讨的对象。
• 第二版强调了 write/read pair,这点其实是和上一个差异点一脉相承的。也就是说,CAP 关注的是对数据的读写操作,而不是分布式系统的所有功能。例如,ZooKeeper 的选举机制就不是 CAP 探讨的对象。
• 第二版除了基本概念,三个基本的设计约束也进行了重新阐述,我来详细分析一下。
1.1 一致性(Consistency)
对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。
1.2 可用性(Availability)
非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。
1.3 分区容错性(Partition Tolerance)
当出现网络分区后,系统能够继续“履行职责”。
1.4 CAP 应用
分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。
2.CAP细节
理论的优点在于清晰简洁、易于理解,但缺点就是高度抽象化,省略了很多细节,导致在将理论应用到实践时,由于各种复杂情况,可能出现误解和偏差,CAP 理论也不例外。如果我们没有意识到这些关键的细节点,那么在实践中应用 CAP 理论时,就可能发现方案很难落地。
而且当谈到数据一致性时,CAP、ACID、BASE 难免会被我们拿出来讨论,原因在于这三者都是和数据一致性相关的理论,如果不仔细理解三者之间的差别,则可能会陷入一头雾水的状态,不知道应该用哪个才好。
CAP 的具体细节,简单对比一下 ACID、BASE 几个概念的关键区别点。
2.1 CAP 关键细节点
2.1.1 CAP 关注的粒度是数据,而不是整个系统。
C 与 A 之间的取舍可以在同一系统内以非常细小的粒度反复发生,而每一次的决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同。
但这句话是理解和应用 CAP 理论非常关键的一点。CAP 理论的定义和解释中,用的都是 system、node 这类系统级的概念,这就给很多人造成了很大的误导,认为我们在进行架构设计时,整个系统要么选择 CP,要么选择 AP。但在实际设计过程中,每个系统不可能只处理一种数据,而是包含多种类型的数据,有的数据必须选择 CP,有的数据必须选择 AP。而如果我们做设计时,从整个系统的角度去选择 CP 还是 AP,就会发现顾此失彼,无论怎么做都是有问题的。
以一个最简单的用户管理系统为例,用户管理系统包含用户账号数据(用户 ID、密码)、用户信息数据(昵称、兴趣、爱好、性别、自我介绍等)。通常情况下,用户账号数据会选择 CP,而用户信息数据会选择 AP,如果限定整个系统为 CP,则不符合用户信息数据的应用场景;如果限定整个系统为 AP,则又不符合用户账号数据的应用场景。
所以在 CAP 理论落地实践时,我们需要将系统内的数据按照不同的应用场景和要求进行分类,每类数据选择不同的策略(CP 还是 AP),而不是直接限定整个系统所有数据都是同一策略。
2.1.2 CAP 是忽略网络延迟的。
这是一个非常隐含的假设,布鲁尔在定义一致性时,并没有将延迟考虑进去。也就是说,当事务提交时,数据能够瞬间复制到所有节点。但实际情况下,从节点 A 复制数据到节点 B,总是需要花费一定时间的。如果是相同机房,耗费时间可能是几毫秒;如果是跨地域的机房,例如北京机房同步到广州机房,耗费的时间就可能是几十毫秒。这就意味着,CAP 理论中的 C 在实践中是不可能完美实现的,在数据复制的过程中,节点 A 和节点 B 的数据并不一致。
不要小看了这几毫秒或者几十毫秒的不一致,对于某些严苛的业务场景,例如和金钱相关的用户余额,或者和抢购相关的商品库存,技术上是无法做到分布式场景下完美的一致性的。而业务上必须要求一致性,因此单个用户的余额、单个商品的库存,理论上要求选择 CP 而实际上 CP 都做不到,只能选择 CA。也就是说,只能单点写入,其他节点做备份,无法做到分布式情况下多点写入。
需要注意的是,这并不意味着这类系统无法应用分布式架构,只是说“单个用户余额、单个商品库存”无法做分布式,但系统整体还是可以应用分布式架构的。例如,下面的架构图是常见的将用户分区的分布式架构。
我们可以将用户 id 为 0 ~ 100 的数据存储在 Node 1,将用户 id 为 101 ~ 200 的数据存储在 Node 2,Client 根据用户 id 来决定访问哪个 Node。对于单个用户来说,读写操作都只能在某个节点上进行;对所有用户来说,有一部分用户的读写操作在 Node 1 上,有一部分用户的读写操作在 Node 2 上。
这样的设计有一个很明显的问题就是某个节点故障时,这个节点上的用户就无法进行读写操作了,但站在整体上来看,这种设计可以降低节点故障时受影响的用户的数量和范围,毕竟只影响 20% 的用户肯定要比影响所有用户要好。这也是为什么挖掘机挖断光缆后,支付宝只有一部分用户会出现业务异常,而不是所有用户业务异常的原因。
2.1.3 正常运行情况下,不存在 CP 和 AP 的选择,可以同时满足 CA。
CAP 理论告诉我们分布式系统只能选择 CP 或者 AP,但其实这里的前提是系统发生了“分区”现象。如果系统没有发生分区现象,也就是说 P 不存在的时候(节点间的网络连接一切正常),我们没有必要放弃 C 或者 A,应该 C 和 A 都可以保证,这就要求架构设计的时候既要考虑分区发生时选择 CP 还是 AP,也要考虑分区没有发生时如何保证 CA。
同样以用户管理系统为例,即使是实现 CA,不同的数据实现方式也可能不一样:用户账号数据可以采用“消息队列”的方式来实现 CA,因为消息队列可以比较好地控制实时性,但实现起来就复杂一些;而用户信息数据可以采用“数据库同步”的方式来实现 CA,因为数据库的方式虽然在某些场景下可能延迟较高,但使用起来简单。
2.1.4 放弃并不等于什么都不做,需要为分区恢复后做准备。
CAP 理论告诉我们三者只能取两个,需要“牺牲”(sacrificed)另外一个,这里的“牺牲”是有一定误导作用的,因为“牺牲”让很多人理解成什么都不做。实际上,CAP 理论的“牺牲”只是说在分区过程中我们无法保证 C 或者 A,但并不意味着什么都不做。因为在系统整个运行周期中,大部分时间都是正常的,发生分区现象的时间并不长。例如,99.99% 可用性(俗称 4 个 9)的系统,一年运行下来,不可用的时间只有 50 分钟;99.999%(俗称 5 个 9)可用性的系统,一年运行下来,不可用的时间只有 5 分钟。分区期间放弃 C 或者 A,并不意味着永远放弃 C 和 A,我们可以在分区期间进行一些操作,从而让分区故障解决后,系统能够重新达到 CA 的状态。
最典型的就是在分区期间记录一些日志,当分区故障解决后,系统根据日志进行数据恢复,使得重新达到 CA 状态。同样以用户管理系统为例,对于用户账号数据,假设我们选择了 CP,则分区发生后,节点 1 可以继续注册新用户,节点 2 无法注册新用户(这里就是不符合 A 的原因,因为节点 2 收到注册请求后会返回 error),此时节点 1 可以将新注册但未同步到节点 2 的用户记录到日志中。当分区恢复后,节点 1 读取日志中的记录,同步给节点 2,当同步完成后,节点 1 和节点 2 就达到了同时满足 CA 的状态。
而对于用户信息数据,假设我们选择了 AP,则分区发生后,节点 1 和节点 2 都可以修改用户信息,但两边可能修改不一样。例如,用户在节点 1 中将爱好改为“旅游、美食、跑步”,然后用户在节点 2 中将爱好改为“美食、游戏”,节点 1 和节点 2 都记录了未同步的爱好数据,当分区恢复后,系统按照某个规则来合并数据。例如,按照“最后修改优先规则”将用户爱好修改为“美食、游戏”,按照“字数最多优先规则”则将用户爱好修改为“旅游,美食、跑步”,也可以完全将数据冲突报告出来,由人工来选择具体应该采用哪一条。
2.2 ACID
ACID 是数据库管理系统为了保证事务的正确性而提出来的一个理论,ACID 包含四个约束,下面我来解释一下。
2.2.1 Atomicity(原子性)
一个事务中的所有操作,要么全部完成,要么全部不完成,不会在中间某个环节结束。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
2.2.2 Consistency(一致性)
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
2.2.3 Isolation(隔离性)
数据库允许多个并发事务同时对数据进行读写和修改的能力。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
2.2.4 Durability(持久性)
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
可以看到,ACID 中的 A(Atomicity)和 CAP 中的 A(Availability)意义完全不同,而 ACID 中的 C 和 CAP 中的 C 名称虽然都是一致性,但含义也完全不一样。ACID 中的 C 是指数据库的数据完整性,而 CAP 中的 C 是指分布式节点中的数据一致性。再结合 ACID 的应用场景是数据库事务,CAP 关注的是分布式系统数据读写这个差异点来看,其实 CAP 和 ACID 的对比就类似关公战秦琼,虽然关公和秦琼都是武将,但其实没有太多可比性。
2.3 BASE
BASE 是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency),核心思想是即使无法做到强一致性(CAP 的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性。
2.3.1 基本可用(Basically Available)
分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
这里的关键词是“部分”和“核心”,具体选择哪些作为可以损失的业务,哪些是必须保证的业务,是一项有挑战的工作。例如,对于一个用户管理系统来说,“登录”是核心功能,而“注册”可以算作非核心功能。因为未注册的用户本来就还没有使用系统的业务,注册不了最多就是流失一部分用户,而且这部分用户数量较少。如果用户已经注册但无法登录,那就意味用户无法使用系统。例如,充了钱的游戏不能玩了、云存储不能用了……这些会对用户造成较大损失,而且登录用户数量远远大于新注册用户,影响范围更大。
2.3.2 软状态(Soft State)
允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。
2.3.3 最终一致性(Eventual Consistency)
系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。
这里的关键词是“一定时间” 和 “最终”,“一定时间”和数据的特性是强关联的,不同的数据能够容忍的不一致时间是不同的。举一个微博系统的例子,用户账号数据最好能在 1 分钟内就达到一致状态,因为用户在 A 节点注册或者登录后,1 分钟内不太可能立刻切换到另外一个节点,但 10 分钟后可能就重新登录到另外一个节点了;而用户发布的最新微博,可以容忍 30 分钟内达到一致状态,因为对于用户来说,看不到某个明星发布的最新微博,用户是无感知的,会认为明星没有发布微博。“最终”的含义就是不管多长时间,最终还是要达到一致性的状态。
BASE 理论本质上是对 CAP 的延伸和补充,更具体地说,是对 CAP 中 AP 方案的一个补充。前面在剖析 CAP 理论时,提到了其实和 BASE 相关的两点:
• CAP 理论是忽略延时的,而实际应用中延时是无法避免的。
这一点就意味着完美的 CP 场景是不存在的,即使是几毫秒的数据复制延迟,在这几毫秒时间间隔内,系统是不符合 CP 要求的。因此 CAP 中的 CP 方案,实际上也是实现了最终一致性,只是“一定时间”是指几毫秒而已。
• AP 方案中牺牲一致性只是指分区期间,而不是永远放弃一致性。
这一点其实就是 BASE 理论延伸的地方,分区期间牺牲一致性,但分区故障恢复后,系统应该达到最终一致性。
综合上面的分析,ACID 是数据库事务完整性的理论,CAP 是分布式系统设计理论,BASE 是 CAP 理论中 AP 方案的延伸。
3. FMEA方法,排除架构可用性隐患的利器
3.1 FMEA 介绍
FMEA(Failure mode and effects analysis,故障模式与影响分析)又称为失效模式与后果分析、失效模式与效应分析、故障模式与后果分析等,专栏采用“故障模式与影响分析”,因为这个中文翻译更加符合可用性的语境。FMEA 是一种在各行各业都有广泛应用的可用性分析方法,通过对系统范围内潜在的故障模式加以分析,并按照严重程度进行分类,以确定失效对于系统的最终影响。
FMEA 最早是在美国军方开始应用的,20 世纪 40 年代后期,美国空军正式采用了 FMEA。尽管最初是在军事领域建立的方法,但 FMEA 方法现在已广泛应用于各种各样的行业,包括半导体加工、餐饮服务、塑料制造、软件及医疗保健行业。FMEA 之所以能够在这些差异很大的领域都得到应用,根本原因在于 FMEA 是一套分析和思考的方法,而不是某个领域的技能或者工具。
回到软件架构设计领域,FMEA 并不能指导我们如何做架构设计,而是当我们设计出一个架构后,再使用 FMEA 对这个架构进行分析,看看架构是否还存在某些可用性的隐患。
3.2 FMEA 方法
在架构设计领域,FMEA 的具体分析方法是:
• 给出初始的架构设计图。
• 假设架构中某个部件发生故障。
• 分析此故障对系统功能造成的影响。
• 根据分析结果,判断架构是否需要进行优化。
FMEA 分析的方法其实很简单,就是一个 FMEA 分析表,常见的 FMEA 分析表格包含下面部分。
3.2.1 功能点
当前的 FMEA 分析涉及的功能点,注意这里的“功能点”指的是从用户角度来看的,而不是从系统各个模块功能点划分来看的。例如,对于一个用户管理系统,使用 FMEA 分析时 “登录”“注册”才是功能点,而用户管理系统中的数据库存储功能、Redis 缓存功能不能作为 FMEA 分析的功能点。
3.2.2 故障模式
故障模式指的是系统会出现什么样的故障,包括故障点和故障形式。需要特别注意的是,这里的故障模式并不需要给出真正的故障原因,我们只需要假设出现某种故障现象即可,例如 MySQL 响应时间达到 3 秒。造成 MySQL 响应时间达到 3 秒可能的原因很多:磁盘坏道、慢查询、服务器到 MySQL 的连接网络故障、MySQL bug 等,我们并不需要在故障模式中一一列出来,而是在后面的“故障原因”一节中列出来。因为在实际应用过程中,不管哪种原因,只要现象是一样的,对业务的影响就是一样的。
此外,故障模式的描述要尽量精确,多使用量化描述,避免使用泛化的描述。例如,推荐使用“MySQL 响应时间达到 3 秒”,而不是“MySQL 响应慢”。
3.2.3 故障影响
当发生故障模式中描述的故障时,功能点具体会受到什么影响。常见的影响有:功能点偶尔不可用、功能点完全不可用、部分用户功能点不可用、功能点响应缓慢、功能点出错等。
故障影响也需要尽量准确描述。例如,推荐使用“20% 的用户无法登录”,而不是“大部分用户无法登录”。要注意这里的数字不需要完全精确,比如 21.25% 这样的数据其实是没有必要的,我们只需要预估影响是 20% 还是 40%。
3.2.4 严重程度
严重程度指站在业务的角度故障的影响程度,一般分为“致命 / 高 / 中 / 低 / 无”五个档次。严重程度按照这个公式进行评估:严重程度 = 功能点重要程度 × 故障影响范围 × 功能点受损程度。同样以用户管理系统为例:登录功能比修改用户资料要重要得多,80% 的用户比 20% 的用户范围更大,完全无法登录比登录缓慢要更严重。因此我们可以得出如下故障模式的严重程度。
• 致命:超过 70% 用户无法登录。
• 高:超过 30% 的用户无法登录。
• 中:所有用户登录时间超过 5 秒。
• 低:10% 的用户登录时间超过 5 秒。
• 中:所有用户都无法修改资料。
• 低:20% 的用户无法修改头像。
对于某个故障的影响到底属于哪个档次,有时会出现一些争议。例如,“所有用户都无法修改资料”,有的人认为是高,有的人可能认为是中,这个没有绝对标准,一般建议相关人员讨论确定即可。也不建议花费太多时间争论,争执不下时架构师裁定即可。
3.2.5 故障原因
“故障模式”中只描述了故障的现象,并没有单独列出故障原因。主要原因在于不管什么故障原因,故障现象相同,对功能点的影响就相同。那为何这里还要单独将故障原因列出来呢?主要原因有这几个:
• 不同的故障原因发生概率不相同
例如,导致 MySQL 查询响应慢的原因可能是 MySQL bug,也可能是没有索引。很明显“MySQL bug”的概率要远远低于“没有索引”;而不同的概率又会影响我们具体如何应对这个故障。
• 不同的故障原因检测手段不一样
例如,磁盘坏道导致 MySQL 响应慢,那我们需要增加机器的磁盘坏道检查,这个检查很可能不是当前系统本身去做,而是另外运维专门的系统;如果是慢查询导致 MySQL 慢,那我们只需要配置 MySQL 的慢查询日志即可。
• 不同的故障原因的处理措施不一样
例如,如果是 MySQL bug,我们的应对措施只能是升级 MySQL 版本;如果是没有索引,我们的应对措施就是增加索引。
3.2.6 故障概率
这里的概率就是指某个具体故障原因发生的概率。例如,磁盘坏道的概率、MySQL bug 的概率、没有索引的概率。一般分为“高 / 中 / 低”三档即可,具体评估的时候需要有以下几点需要重点关注。
• 硬件
硬件随着使用时间推移,故障概率会越来越高。例如,新的硬盘坏道几率很低,但使用了 3 年的硬盘,坏道几率就会高很多。
• 开源系统
成熟的开源系统 bug 率低,刚发布的开源系统 bug 率相比会高一些;自己已经有使用经验的开源系统 bug 率会低,刚开始尝试使用的开源系统 bug 率会高。
• 自研系统
和开源系统类似,成熟的自研系统故障概率会低,而新开发的系统故障概率会高。
高中低是相对的,只是为了确定优先级以决定后续的资源投入,没有必要绝对量化,因为绝对量化是需要成本的,而且很多时候都没法量化。例如,XX 开源系统是 3 个月故障一次,还是 6 个月才故障一次,是无法评估的。
3.2.7 风险程度
风险程度就是综合严重程度和故障概率来一起判断某个故障的最终等级,风险程度 = 严重程度 × 故障概率。因此可能出现某个故障影响非常严重,但其概率很低,最终来看风险程度就低。“某个机房业务瘫痪”对业务影响是致命的,但如果故障原因是“地震”,那概率就很低。例如,广州的地震概率就很低,5 级以上地震的 20 世纪才 1 次(1940 年);如果故障的原因是“机房空调烧坏”,则概率就比地震高很多了,可能是 2 年 1 次;如果故障的原因是“系统所在机架掉电”,这个概率比机房空调又要高了,可能是 1 年 1 次。同样的故障影响,不同的故障原因有不同的概率,最终得到的风险级别就是不同的。
3.2.8 已有措施
针对具体的故障原因,系统现在是否提供了某些措施来应对,包括:检测告警、容错、自恢复等。
• 检测告警:最简单的措施就是检测故障,然后告警,系统自己不针对故障进行处理,需要人工干预。
• 容错:检测到故障后,系统能够通过备份手段应对。例如,MySQL 主备机,当业务服务器检测到主机无法连接后,自动连接备机读取数据。
• 自恢复:检测到故障后,系统能够自己恢复。例如,Hadoop 检测到某台机器故障后,能够将存储在这台机器的副本重新分配到其他机器。当然,这里的恢复主要还是指“业务”上的恢复,一般不太可能将真正的故障恢复。例如,Hadoop 不可能将产生了磁盘坏道的磁盘修复成没有坏道的磁盘。
3.2.9 规避措施
规避措施指为了降低故障发生概率而做的一些事情,可以是技术手段,也可以是管理手段。例如:
• 技术手段:为了避免新引入的 MongoDB 丢失数据,在 MySQL 中冗余一份。
• 管理手段:为了降低磁盘坏道的概率,强制统一更换服务时间超过 2 年的磁盘。
3.2.10 解决措施
解决措施指为了能够解决问题而做的一些事情,一般都是技术手段。例如:
• 为了解决密码暴力破解,增加密码重试次数限制。
• 为了解决拖库导致数据泄露,将数据库中的敏感数据加密保存。
• 为了解决非法访问,增加白名单控制。
一般来说,如果某个故障既可以采取规避措施,又可以采取解决措施,那么我们会优先选择解决措施,毕竟能解决问题当然是最好的。但很多时候有些问题是系统自己无法解决的,例如磁盘坏道、开源系统 bug,这类故障只能采取规避措施;系统能够自己解决的故障,大部分是和系统本身功能相关的。
3.2.11 后续规划
综合前面的分析,就可以看出哪些故障我们目前还缺乏对应的措施,哪些已有措施还不够,针对这些不足的地方,再结合风险程度进行排序,给出后续的改进规划。这些规划既可以是技术手段,也可以是管理手段;可以是规避措施,也可以是解决措施。同时需要考虑资源的投入情况,优先将风险程度高的系统隐患解决。
例如:
• 地震导致机房业务中断:这个故障模式就无法解决,只能通过备份中心规避,尽量减少影响;而机柜断电导致机房业务中断:可以通过将业务机器分散在不同机柜来规避。
• 敏感数据泄露:这个故障模式可以通过数据库加密的技术手段来解决。
• MongoDB 断电丢数据:这个故障模式可以通过将数据冗余一份在 MySQL 中,在故障情况下重建数据来规避影响。
4.高可用存储架构:双机架构
高可用存储架构中常见的双机架构,分别为主备复制、主从复制、双机切换和主主复制。
5.高可用存储架构:集群和分区
6.如何设计计算高可用架构
计算高可用的本质是通过冗余来规避部分故障的风险。
计算高可用架构的设计复杂度主要体现在任务管理方面。因此,计算高可用架构设计的关键点有下面两点。
6.1 哪些服务器可以执行任务
第一种方式:每个服务器都可以执行任务。
第二种方式:只有特定服务器(通常叫“主机”)可以执行任务。当执行任务的服务器故障后,系统需要挑选新的服务器来执行任务。
6.2 任务如何重新执行
第一种策略是对于已经分配的任务即使执行失败也不做任何处理,系统只需要保证新的任务能够分配到其他非故障服务器上执行即可。
第二种策略是设计一个任务管理器来管理需要执行的计算任务,服务器执行完任务后,需要向任务管理器反馈任务执行结果,任务管理器根据任务执行结果来决定是否需要将任务重新分配到另外的服务器上执行。
接下来,我将详细阐述常见的计算高可用架构:主备、主从和集群。
7.业务高可用的保障:异地多活架构
7.1 什么是异地多活?
• 异地多活:异地指不同地理位置,多活指不同地理位置的系统都是活跃的,都能够提供业务服务。
• 异地多活是为了解决极端场景下所有服务器都出现故障时业务不受影响,或者业务在几分钟内就能够快速恢复而设计的。
• 异地多活的优点:功能强大、提供更好的体验、可以减少业务中断带来的损失
• 异地多活的缺点:代价高昂、设计复杂
7.2 应用场景
• 无法承受异地多活带来的复杂度和成本时可以只做异地备份,不做异地多活
• 业务中断后对用户影响很大的系统需要做异地多活
• 业务规模很大,中断后影响收入的系统需要做异地多活
7.3 架构模式
根据地理位置上的距离分为同城异区、跨城异地、跨国异地3种架构模式
7.3.1 同城异区
• 定义:将业务部署在同一个城市不同区的多个机房
• 优缺点:设计复杂度非常低、成本相对较低、极端灾难无法应对
• 应用场景:应对机房级别故障的最优架构
7.3.2 跨城异地
• 定义:业务部署在不同城市的多个机房,而且距离最好要远一些
• 优缺点:可以有效应对范围较大的极端灾难、架构复杂度很高
• 应用场景:对数据一致性要求不那么高,或者数据不怎么改变,或者即使数据丢失影响也不大的业务
7.3.3 跨国异地
• 定义:业务部署在不同国家的多个机房
• 优缺点:不是真正意义的多活、适合特殊类型业务
• 应用场景:为不同地区的用户提供服务、只读类的业务
8.异地多活设计4大技巧
异地多活的本质:通过异地的数据冗余,来保证在极端异常的情况下业务也能够正常提供给用户,异地多活架构设计的核心是数据同步
设计核心思想:采用多种手段,保证绝大部分用户的核心业务异地多活
8.1 技巧一:保证核心业务的异地多活
• 不要陷入『保证所有业务都能“异地多活”』的思维误区
• 识别核心业务,优先实现核心业务的异地多活架构
8.2 技巧二:保证核心数据最终一致性
• 不要陷入『所有数据都实时同步』的思维误区
• 物理距离导致无法实现数据快速同步的问题是无解的,只能尽量减少影响
• 尽量减少机房距离、尽量减少数据同步、只保证最终一致性
3、技巧三:采用多种手段同步数据
• 不要陷入『只使用存储系统的同步功能』的思维误区
• 多种手段配合存储系统的同步来使用,或者不采用存储系统的同步方案
4、技巧四:只保证绝大部分用户的异地多活
• 不要陷入『我要保证业务 100% 可用』的思维误区
• 异地多活也无法保证 100% 的业务可用
• 可以采取一些措施进行安抚或者补偿受影响的用户
9.跨城异地多活架构的设计流程
9.1 第一步:业务分级
• 按照一定的标准将业务进行分级,挑选出核心的业务
• 分级标准:访问量大的、核心业务、产生大量收入的
9.2 第二步:数据分类
• 对核心业务相关的数据进一步分析,识别所有的数据及数据特征
• 常见数据特征分析纬度:数据量、数据唯一性、实时性、可丢失性、可恢复性
9.3 第三步:数据同步
• 根据不同的数据设计不同的同步方案
• 常见数据同步方案:存储系统同步、消息队列同步、重复生成
9.4 第四步:异常处理
• 假设在出现同步延迟、数据丢失、数据不一致等问题时,系统将采取什么措施来应对
• 目的是避免整体业务不可用、在问题恢复后修正异常数据、安抚用户弥补损失
• 常见异常处理措施:多通道同步、同步和访问结合、日志记录、用户补偿
10.如何应对接口级的故障?
接口故障是指机器并没有停机,网络也正常。但业务出现问题,比如响应缓慢,超时等异常。这种问题一般都是服务器压力过大导致的。
解决方案:
10.1 降级
就是停掉一些非核心的业务功能。例如双11的时候,订单数量不显示。不支持售后服务等。保证核心功能的使用。
10.2 熔断
熔断和降级的区别:
• 降级针对的是应对自身系统故障。
• 熔断是应对外部系统故障情况。例如果A系统的X功能依赖B系统的接口,但B系统接口执行缓慢导致A系统的大量线程被卡住,A系统将会挂掉。处理方式就是当A系统的X功能有调用B系统接口前直接返回错误,不进行调用。
• 熔断机制实现关键就是有一个统一的API调用层,由API调用层来进行采样分析。接口调用散落在代码的各处就没法处理。
10.3 限流:
基于请求的限流:简单来说就是单位时间内允许的请求数量。
基于资源的限流:是从系统内部资源考虑的,常见的内部资源有:连接数,文件句炳,线程数,请求队列等。
例如使用队列接收请求,当超过队列大小时直接拒绝后面的请求。
10.4 排队:想想12306就明白了
由于排队需要临时缓存大量的业务请求(夯住请求不直接不响应)。所以一般都需要独立的消息队列系统缓存。