《从0开始学架构》——高可用:异地多活和接口级故障

本系列是极客时间《从0开始学架构》的读书笔记。

一、异地多活

对应《28 | 业务高可用的保障:异地多活架构》《29 | 异地多活设计4大技巧》《30 | 异地多活设计4步走》

在上一篇提到过,如果部分节点的故障是地理级别的话,最好做数据分区备份架构。但是,由于备份系统正常情况下是不对外提供服务的,所以把备份数据恢复到正常情况,需要很长时间。
这个很长时间,并不是指的系统启动的时间,而是由于备份系统平时没有流量,如果直接上线可能会触发平常测不到的问题;备份系统也没有中间数据、缓存数据,如果不经过预热直接切换,大流量会直接拖垮系统;即使是再实时的系统也会有数据延迟,如果是金融类系统需要确保数据一致。许多方面的考虑,都不能保证备份系统能够实时切换上线。

如果业务需要在此种故障背景下,依然要能够不受影响或只影响几分钟,那么就需要考虑异地多活架构。

应用场景

异地,指的是地理上位于不同位置,多活指的是都能对外提供服务。一个系统符合异地多活,需要满足:正常情况下,用户无论访问哪个地点的业务系统,都能得到正确的服务;当某个地点的服务异常时,用户访问其他地方的系统,可以得到正确的服务。

这种架构的代价很高:系统的复杂度会发生本质变化,成本大幅上升。
所以,是否选择异地多活,要看业务的具体情况。一般而言,核心的、关键的业务才会去考虑。

架构模式

依据地理位置划分。

1.同城异区。
这种架构不能应对极端故障(如城市停电、地震、洪水……),但是由于处于同一个城市,可通过搭建专用网络实现和在同一个机房内几乎一样的速度。这样就减少了设计的复杂度以及相应的成本。
这种架构可以很好地应对机房故障、火灾等场景。由于此类故障场景发生概率更大,所以综合考虑,同城异区架构是应对机房级别故障的最优选择。

2.跨城异地。
选址时距离要尽量远,这样才能应对城市级别的极端故障。
由于距离非常远,量变引起质变,机房之间的传输速度急剧下降,并且传输线路的可用性难以可控(如挖掘机把光缆挖断导致支付宝故障、中美海底光缆被拖船扯断导致一系列故障)。这些由于距离导致的网络延迟,一定会造成数据的不一致。
如果数据要求强一致性,如银行存款、支付宝余额,那么就无法做到真实的跨城异地多活。一般这种金融相关的系统,只会做同城异区架构。
而一致性要求不高的数据,或数据不经常改变,或丢失了也不影响业务,这类场景就可以考虑跨城异地多活。如登录信息、新闻类网站。

3.跨国异地。
由于地理距离进一步加剧,网络时延达到了秒级,不再符合异地多活的第一条要求(正常情况下,用户无论访问哪个地点的业务系统,都能得到正确的服务)。
因此跨国异地的多活概念与上面两种不同。
应用场景有:为不同地区的用户提供服务,如亚马逊,有美亚、日亚、中亚,等等;只读类业务做多活,如谷歌的搜索服务。

跨城异地架构详解

由于同城异区可通过高速网络互连,可以当作仍在同一机房内,所以架构设计时按本地机房设计,无须额外考虑。而跨国异地,由于定义不同,架构设计实际上不难。
只有跨城异地,数据不一致肯定会出现,需要确保在此情况下业务不受影响或影响很小,所以它是异地多活架构中复杂度最高的。

四个设计技巧:

1.保证核心业务的异地多活
比如相对于注册来说,很显然登录才是核心业务。

2.保证核心数据最终一致性
异地多活本质上是通过数据的多份冗余备份,来保证服务的多活,因此数据同步是异地多活架构的设计的核心。

然而如前所述,由于存在物理限制,多个数据中心之间无法做到快速同步。所谓的同步速度是与同机房之间同步,或系统内CPU读写、内存读写、硬盘读写这种速度相比较的。比方说,CPU大概是纳秒级,硬盘大概是毫秒级,而异步多活架构的话,一般是在秒级。

因此,为了尽可能地提速,需要尽量减少异地多活机房间的距离,可搭建高速网络;尽量减少数据同步,只同步核心业务相关数据;保证最终一致性,不保证实时一致性,也就是之前提到的BASE理论和CAP理论的区别。

3.采用多种手段同步数据。
首先可以使用存储系统本身的复制同步功能。当然,由于这些功能本身并不是为了异步多活场景设计的,会有各种问题,比如说不能够依据业务设置什么时候同步,是全量同步还是增量同步,等等。
所以一般都会以存储系统本身的复制功能为基础,综合其他手段做配合,做定制开发。

这些配合手段包括,使用消息队列;使用二次读取方式,指的是在B中心读取失败,路由到A中心进行重试读取;使用回源读取方式,B中心判断数据属于A中心,直接路由到A中心进行读取;使用重新生成数据,A宕机,B读取失败,则尝试在B生成新数据(如用户session可用此方法)。

如果存储系统出现了数据冲突,需要对数据进行清理合并。常用的方法有通过全局唯一ID,通过时间戳,等等。有时也要求业务系统对这种数据冲突提供处理逻辑。

4.只保证绝大部分用户的异地多活
现实就是这样,系统设计时不得不去考虑这种情况下应该如何处理。大部分都是需要业务系统来配合。

比如,银行的转账业务,由于不能保证账户的实时一致性,所以不提供实时转账功能,而是提供转账申请+转账确认两个功能。通过牺牲用户体验,来保证数据的安全性和实时一致性。

除此之外,还可以通过挂公告、事后补偿、补充体验(转账成功后通过短信通知用户,这样就不需要用户主动去查询转账状态,提高用户体验)等方式,来对用户进行安抚或补偿。

综上,异地多活设计理念就是:通过多种手段,保证绝大部分用户的核心业务异地多活。

如果底层存储使用了OceanBase这样的分布式强一致性数据存储系统,也很难做到和业务无关的异地多活。好处是不需要考虑持久层的跨地域数据同步问题,但是时延变长,会对业务造成影响。另外业务系统的缓存层异地多活问题,依然未能解决。

跨城异地多活架构设计步骤

在上面提到的4大技巧的基础上,跨城异地多活架构分为四个步骤。

第1步:业务分级

目的是找出核心业务,为核心业务提供异步多活。可依据访问量划分,依据产生的收入划分,依据是否是关键业务划分(QQ聊天 VS QQ空间)。

第2步:数据分类

识别出核心业务后,需要对数据分析,识别出所有的数据和数据特征。

常见的数据特征维度有:
数据量,包括总的数据量以及新增、修改、删除的数据量,这种类型的数据都需要同步。
唯一性,数据是否需要确保多个机房产生的数据必须唯一,比如用户ID、手机等数据。
实时性,要求数据必须在多长时间内同步到其他机房,实时性要求越高,设计越复杂。
可丢失性,如session丢失后重新生成就可以了。
可恢复性,数据丢失后,是否可通过手段恢复。

第3步:数据同步

确定数据的特点后,可依据不同的数据设计不同的方案。

常见的数据同步方案有(之前提到的4大技巧中的第三点):
存储系统同步,优点是简单,缺点是不能定制化。
消息队列同步,适合无事务性或无时序性的数据。
重复生成,适合可以重复生成的数据。

第4步:异常处理

无论同步方案如何设计,总会出现异常情况,如同步延迟、数据丢失、数据不一致等。异常处理就是针对这种场景,其目的是保证问题发生时,不会因部分数据异常而导致业务不可用,同时异常恢复后要能够对数据进行修正,以及对用户必要的补偿措施。

常见的异常处理措施有:
多通道同步,指的是使用两种数据同步方式,若采用更多的话得不偿失,两种数据同步方式需要使用不同的网络连接,同时数据要求没有时序要求。
同步和访问结合方式,指的是多个机房间除了可以通过数据同步来获取数据外,还可以通过访问接口获取数据,要求不使用同样的网络连接,优先读取本地数据,无法读取再请求其他机房,同时数据有路由规则,当A机房确定数据不属于A时,要能够明确判断得知是访问B还是C机房。这样可以降低跨机房的异地访问量,适合实时性要求高的数据。
日志记录方式,用于异常恢复后的数据修正,可在服务器上保存日志,也可在本地独立系统保存,还可异地保存,分别对应服务器异常、机房内机架异常、机房异常。
用户补偿,系统的方案是保证99.99%的用户在故障的场景下业务正常,人工补偿是对应剩下的0.01%。

二、接口级故障

对应《31 | 如何应对接口级的故障?》

异地多活是为了应对系统级的故障。对于接口级的故障,虽然影响相对系统级故障较小,但是发生概率较高。

接口级故障的典型表现是系统和网络都正常,但是业务故障了。如,当系统某项资源负载太高,导致业务响应缓慢。

有可能是由于程序逻辑不完善有bug导致,如耗尽了内存,耗尽了和数据库的连接数。也有可能是外部攻击、第三方大量请求,或是促销或活动导致的业务量暴涨导致。

解决接口级故障的核心思想同异步多活:优先保障核心业务和优先保障绝大部分用户。下面是几种常见方式。

降级

指的是将系统的某些业务或接口降低,可以是只提供部分功能,也可以完全停掉。如论坛只允许看帖子,不允许发帖子和修改帖子。如电商平台,不允许参与活动,只能浏览和购买。如电商平台,不允许支付,只能下单。

核心思想是,优先保障核心业务,主流程要跑通。

常见方式有:
系统后门降级。预先定义好降级操作,当需要时,可通过访问url等方式进行触发。优点是实现简单。缺点是无法批量,无法实现复杂的权限管理。
独立降级系统。将降级操作独立成一个单独的系统,实际中,可在业务开发时就确定好对应的开关,便于一键降级。

熔断

熔断和降级有点类似,不同的是,降级是为了应对系统内部故障,而熔断则是为了应对依赖的外部系统故障。

如A服务的X功能依赖B服务,当B服务响应过慢时,A服务的X功能也受到影响,从而拖慢A服务的其他功能。这时使用熔断机制,X功能不再请求B服务,而是直接返回失败,避免A服务被B服务拖死。

熔断机制需要设置阈值,一般是先设置然后上线后观察效果再调优。同时,需要有一个统一的API调用层,对API调用进行采样和统计。

限流

指的是只允许系统能够承载的流量进入系统,超过的将被丢弃。
降级是从系统功能优先级角度来应对故障,而限流则是从用户访问压力的角度来考虑。

常见的有:
基于请求限流,如限制总量,限制时间量。限制总量指的是某个指标的累积总量,而限制时间量指的是一段时间内指标的累积量。
如微信的服务号,就对各种指标进行了限制
同熔断一样,需要考虑如何找到合适的阈值。
基于资源限流。对系统内部的资源的上限进行规定,如连接数、文件句柄、线程数等。
在操作系统内部,其本身已经对最大文件句柄进行了规定。
难点是找到关键资源和对关键资源的阈值取值。

排队

排队是限流的一个变种。限流是直接拒绝用户,排队是让用户等待一段时间。需要用独立系统来保存用户的请求,如消息队列。

对于这些理论,可以找一找业界的开源方案,进行对照学习,如:饿了么异地多活技术实现(一)总体介绍,其中虽然没有提炼,但是可以看出,是为了优先保障核心业务和保障绝大部分用户而设计的。
y

没有更多推荐了,返回首页