架构设计-异地多活

参考:

https://blog.csdn.net/suifeng629/article/details/89326048?utm_medium=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase&depth_1-utm_source=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase

https://www.jianshu.com/p/aff048130bed

https://www.jianshu.com/p/c25676f54308

https://www.infoq.cn/article/interview-alibaba-bixuan

异地多活架构

异地指地理位置上的不同,多活指不同地理位置上的系统都能够提供业务服务。

判断标准:

  1. 正常情况下,用户无论访问哪一个地点的业务系统,都能够得到正确的业务服务。

  2. 某地异常时,用户访问其他地方正常的业务系统,能够得到正确的业务服务。

异地多活的代价:

  1. 系统复杂度会有质的变化。

  2. 成本大大增加。

架构模式

1. 同城异区

部署在同一个城市不同区的机房,用专用网络连接。

同城异区两个机房距离一般就是几十千米,网络传输速度几乎和同一个机房相同,降低了系统复杂度、成本。

这个模式无法解决极端的灾难情况,例如某个城市的地震、水灾,此方式是用来解决一些常规故障的,例如机房的火灾、停电、空调故障。

2. 跨城异地

部署在不同城市的多个机房,距离要远一些,例如北京和广州。

此模式就是用来处理极端灾难情况的,例如城市的地震、相邻城市的大停电。

跨城异地主要问题就是网络传输延迟,例如北京到广州,正常情况下的RTT(Round-Trip Time 往返时延)是50毫秒,当遇到网络波动等情况,会升到500毫秒甚至1秒,而且会有丢包问题。

物理距离必然导致数据不一致,这就得从“数据”特性来解决,如果是强一致性要求的数据(如存款余额),就无法做异地多活。

举例,存款余额支持跨城异地多活,部署在北京和广州,当光缆被挖断后,会发生:

  • 用户A余额有10000,北京和广州是一致的。

  • A在广州机房给B转5000,广州余额为5000,由于网络不通,北京此时的余额为10000。

  • A在北京发现余额还是10000,给C转10000,由于网络不通,广州的余额为5000。

  • A在广州又可以给D转5000。

这就出事儿了,所以这类数据不会做跨城异地多活,只能用同城异区架构,因为同城的网络环境要好很多,可以搭建多条互联通道,成本也不会太高。

跨城异地模式适用于对数据一致性要求不高的场景,例如:

  1. 用户登录,数据不一致时重新登录即可。

  2. 新闻网站,一天内新闻数据变化较少。

  3. 微博网站,即使丢失一点微博或评论数据也影响不大。

3. 跨国异地

部署在不同国家的多个机房。

此模式的延时就更长了,正常情况也得几秒,无法满足正常的业务访问。

所以,跨国异地多活适用于:

  • 为不同地区用户提供服务

例如,亚马逊美国是为美国用户服务的,亚马逊中国的账号是无法登录美国亚马逊的。

  • 只读类业务

例如谷歌的搜索,不管用户在哪个国家搜索,得到的结果基本相同,对用户来说,跨国异地的几秒延迟,对搜索结果没什么影响。

跨城异地多活设计技巧

1. 保证核心业务的异地多活

思维误区:要保证所有业务都能异地多活。

假设用户子系统,负责注册、登录、用户信息这3个业务,由于有海量用户,所以对用户进行分区,分配到不同数据中心,正常情况下某个用户属于某个主分区,并在其他分区也有备份,通过hash计算得出属于哪个中心。

如果想要保证注册业务多活,可能会有问题,例如,A中心注册了用户,数据还未同步到B中心时A宕了,为了支持多活,需要可以让用户到B中心重新注册,但一个手机号只能注册一个账号,A恢复后就有冲突了。

如果要保证用户信息业务多活,也会有问题,例如,A、B两个中心在异常情况下都修改了用户信息,如何处理冲突?

可以发现,注册、登录、用户信息这3个业务都支持多活的话,是非常难的,有的问题甚至是无解的。解决的方法就是:优先实现核心业务的异地多活。

这个示例中,“登录”才是核心业务,例如系统的日活是1000万,每天的注册可能是几万,修改用户信息的可能还不到1万,但登录是1000万,很明显要保证登录的异地多活。

2. 保证核心数据最终一致性

思维误区:要保证所有数据实时同步。

由于物理上的限制,所有数据都实时同步,是一个无法达到的目标。

必须要尽量减少数据同步,只同步核心业务相关的数据。

例如上面的例子,登录产生的token或session信息,数据量很大,实际上不需要同步到其他中心,即使丢失了重新登录就可以了,会影响用户体验,但是可以接受的。

3. 采用多种手段同步数据

思维误区:只使用存储系统的同步功能。

存储系统本身就有强大的同步功能,例如 mysql redis 都可以很好的实现同步,但某些场景下是无法满足需要的,所以要使用多种手段配合,例如:

  • 消息队列

创建账号后,将账号数据通过消息队列同步到其他业务中心。

  • 二次读取

例如用户在A中心注册了,然后访问了B中心,此时B还没有拿到账号数据,为了解决这个问题,B中心在读取本地数据失败时,可以根据路由规则,再去A中心访问一次。

  • 回源读取

例如session数据没有同步,用户在A中心登录,B中心可以拿着 session id 到A中心请求session数据。

4. 只保证绝大部分用户的异地多活

思维误区:要保证业务 100% 可用。

物理规律决定了异地多活无法保证100%的业务可用。

以转账业务为例,在北京和上海两个中心实现了实时转账的异地多活,在异常情况下会出现问题,例如用户有一万存款,在北京给人转了一万,又到上海给人转了一万。

所以,无法做到实时转账的异地多活,需要通过特殊业务受到实现。

例如,除了“实时转账”外,还提供“转账申请”业务,用户在上海提交了转账请求,并不立即转账,而是后台异步处理,如果发现北京中心不可用,就等待重试,北京恢复后,如果发现余额不足就转账失败。

这个方式牺牲了一些用户体验,本来一次完成的操作变为了2次,一次提交转账申请,另一次是确认转账结果。

对于用户体验,可以采取一些补偿措施,例如:

  • 公告

例如由于xxx原因导致您的不便,技术哥哥正在紧急处理等等。

  • 事后补偿

例如送代金券、小礼品等。

  • 补充体验

例如上面的转账例子,可以在转账结果出来后给用户发个短信,减少用户不时的登录查看。

小结

三地五中心(1)

昨天科技圈最火的新闻应该是“AWS中国区光缆被挖,导致三星、小米等众多企业服务不可用”。
又是光缆被挖,咦!?为什么是又,让我们来一起回到过去:

  • 2019.6.02:亚马逊光缆被挖断,国内部分地区网络出现异常
  • 2019.3.23:施工队挖断腾讯光纤,致腾讯旗下100多款游戏受影响,损失大了
  • 2015.5.27:由于杭州市萧山区某地光纤被挖断,造成目前少部分用户无法使用支付宝

我这里只是列出来了几家大公司所涉及到的光缆被挖事故,其余还包括什么广电光缆被挖,社保局光缆被挖就不列了,感兴趣的自己去百度。

好,我们发现“公司再大,也怕施工队”,那么这种事故能怪施工队吗?个人觉得不能把责任都推给施工队,当然我们这里不讨论这些,我们做为大公司,我们以后怎么预防这种现象呢?
这个我们可以来看下支付宝的解决办法,毕竟它老人家在2015年就经历过这种惨况了。

2018年9月20日,杭州云栖大会ATEC主论坛现场上演了一场特别的技术秀。蚂蚁金服副CTO胡喜现场模拟挖断支付宝近一半服务器的光缆。结果只过了26秒,模拟环境中的支付宝就完全恢复了正常。

这种解决办法就是“三地五中心”,这是一种机房架构,即在三座城市部署五个机房,一旦其中一个或两个机房发生故障,依靠技术可以将故障城市的流量全部切换到运行正常的机房。
那么在“三地五中心”之前还存在很多其他架构,我们一一来看一下他们的特点。

灾难演进

最初,我们把应用(一个非常简单的只读应用,比如一个显示Hello World的网页,不考虑数据存储)只放在一个机器上,那么当这个服务器down机了,我们的应用便不可用了。
所以,我们考虑把我们的应用放在多个机器上,在公司单独开辟一个机房来放置这些机器,这样单独某一个台机器down机了并不影响我们的应用。
但是,如果你们公司某一天停电了呢?这个时候我们就考虑在这座城市的另外一个地方在放置一个机房,这是应用就被部署在了同城的两个机房(这个叫同城双活
但是,如果你们城市某一天经历了海啸、台风、地震等自然灾害,两个机房都不能使用了,这个时候我们就会考虑在另外一个城市再搭建一个机房来部署我们的应用,这样我们应用的可用性就更高了(这个叫异地多活)。
好,到此为止不管出现什么样的状况,我们的应用基本上都可用(除非地球毁灭...)

那么我们上面考虑的应用是一个非常简单的只读应用,所以各个地方的应用是可以同时对外提供服务的,那么如果我们的应用涉及到数据存储,这个时候各个地方的应用就不能同时对外提供写入数据的服务了,因为很有可能会出现数据冲突,那么我们暂且规定只有公司内部机房里的服务器(后文我们叫主机房)可以提供写数据服务,而同城的另外一个机房以及异地的另外一个机房只能从主机房同步数据,这样这两个地方的机房的功能就叫灾备,因为数据会同步,所以就算主机房停电了,另外两个机房还是可以临时来对外提供服务的。所以现在的架构可以如下:

 
image.png

当主机房停电后,用户会去请求北京备份机房,当北京备份机房也停电后,用户会去请求上海备份机房。
好,对于这个架构,我们刚刚说只有主机房能对外提供服务,另外两个机房都只是作为容灾的备份,那么也就是说备份机房利用率不高,因为毕竟正常请求下主机房不可能老停电,所以对于备份机房能不能提高它的利用率呢?当然可以,我们可以让北京的备份机房也去接收部分业务请求,只是这些请求可以没那么重要,比如一些读请求,而上海的备份机房不去接收请求,还是单纯作为容灾备份机器,因为如果谁都不能保证当备份机房接收业务请求会不会出现其他不可预知的问题,那么现在三个机房的角色实际上已经有些不同了:
 
image.png

这个就叫两地三中心

那么两地三中心这种架构是目前很多银行或大型企业正在使用的一种架构,因为国家针对银行的灾备能力做过要求,资产超过多少多少的一定要做两地三中心架构,以保证银行系统的稳定。

那么这种架构有没有它的缺点呢?我们来考虑一下它的可用性高不高?可用性的意思就是这个架构处理用户请求时够不够快?
我们发现这种架构,中心之间是需要数据备份的,那么对于数据备份只有两种方式,要么异步,要么同步。

  • 最大性能模式:如果是异步,表示用户一个写数据请求,只要在生产数据中心存储完数据后就会直接返回结果给用户,同时异步去备份数据,但是,如果正准备去异步备份数据的时候生产数据中心停电了~,那么这个时候还能将灾备服务器暴露出去给用户提供服务吗?不能了,因为很有可能灾备中心的数据是过时的数据。
  • 最大保护模式:如果是同步,表示用户一个写数据请求,不仅要等待生产数据中心存储完数据,还需要等其他灾备中心备份完数据后才能返回,而且仅仅当灾备中心出现问题时,因为不能完成数据的备份,所以整个架构也不能对外提供服务,这种可用性是很低的。
  • 最大可用模式:这是普遍采用的方案,正常情况下使用最大保护模式,同时生产数据中心监控灾备数据中心,一旦发现某一灾备中心出现了问题,那么则会改为最大性能模式,这样就保证了生产数据中心不受其他灾备中心影响。
  • 三写两同步:这是阿里之前的架构模式,意思是同城三个中心,数据备份不是发生在数据库层面,而是应用层,当应用向数据库去写数据时,会同时向三个中心去写数据,只要有两个中心返回成功即可,这样就算三个中心有一个中心停电了,那么并不影响整个架构的高可用,这个思路和我们前面三种是不一样的,性能肯定会高很多。

好,我们介绍了一下两地三中心,总结一下它的缺点:

  1. 灾备中心利用率不高
  2. 生产数据中心停止运行后,灾备中心中不一定有100%一模一样的数据
  3. 成本高,但又无法真正实现期望的高可用能力

那么为了解决这个问题,就出现了三地五中心,虽然名字和两地三中心类似,但提供的功能完全不同。

三地五中心是指三个城市,5个中心,三地五中心基于的概念是单元化,还得花很大篇幅来讲,下一篇继续吧。

三地五中心(2)

上篇文章我们总结了一下同城双活、异地多活、两地三中心等一些部署架构,那么这篇文章我来发表一下我对三地五中心的理解。

我们上篇文章讲过两地三中心这个架构,如下图:


image.png
image.png

这种架构具备容灾能力,比如生产数据中心停电了,那么可以把所有流量都切到同城灾备中心或异地灾备中心,那么现在的问题是假如真到了停电的那一天,你敢把所有的流量都切到灾备中心去吗?
上篇文章说了,灾备中心它主要的功能是作为生产数据中心的一个备份,所以它并没有如同生产数据中心一样不停的在对外提供服务,那么就有问题了,灾备相当于一个新人,一个一直在模仿大哥的一个新人,现在大哥受伤了,按道理是应该小弟顶上,但是小弟还是个新人,硬顶上去是不是很有可能会出错?也就是说:

  • 第一,不能保证灾备中心有能力接管线上所有的用户流量,可能刚已接收灾备中心被压垮,或者出现其他各种各样预估不到的错误;
  • 第二,如果生产数据中心接收了用户的写请求,还没来得及同步到灾备中心,这个时候停电了,这种情况下,也不能直接把用户流量切到灾备中心。

所以基于上面的分析,并不是说灾备中心一定不能顶上,只是在顶上之前可能还要做很多其他的检查和准备,这个时间是不确定的,至少不会很快...。

那么问题来了,该怎么办?

首先对于上面列出来的两点中的第一点,如果我们能够让灾备中心不再仅仅只能用来做灾备,还能和生产数据中心一样正常的对外提供服务呢?如下图:


image.png
image.png

可以看到上面的架构图:

  • 不再区分生产数据中心和灾备数据中心,只有数据中心,而且数据中心之间相互备份数据,保证每个数据中心都是全量数据。
  • 用户可以在任意一个数据中心上进行读写操作。

好,首先我们不管这种架构能不能实现,至少它的好处是非常明显的:

  1. 每个数据中心一直在对外提供服务(不是一个新手),所以当一个数据中心停电后,直接把用户流量切到另外一个数据中心也是问题不大的。
  2. 用户可以就近访问数据中心,这样用户的体验更好,并且整个架构的流量也比较平均。

优点很明显,如果能实现就再好不过了,那么这种架构实现起来最重要的一点就是:用户同时向不同数据中心写入数据,数据中心双向同步数据时,如果出现冲突该如何解决?
那么这个问题,目前阿里和蚂蚁金服的解决办法是:将用户按某一个规则进行分组,每组用户写入数据时只能写入到指定的数据中心,相当于用户与数据中心绑定在一起了,这样保证了数据中心在双向同步之前数据是不会冲突的,因为按用户分组了,不同用户的数据不会冲突。
当然思路非常简单,但是实现起来肯定是非常麻烦的,但是思路肯定是可以的,阿里也用实践证明了,我们先把上面的架构稍微完善一下:

image.png
image.png

用户使用网站时,由运营商网络或CDN选择最近的机房,机房内部署一个负载均衡,由这个负载均衡最终判断用户属于机房(前文中的数据中心),也就是可能出现,用户在注册时在北京,那么他的uid就和北京某个机房绑定了,那么当这个用户在上海使用时,会由上海的负载均衡按照用户分组规则将请求转发到北京绑定的那个机房去(当然并不是所有请求,比如读请求肯定可以直接在上海机房进行读取,所以具体的实现都要看业务怎么实现了,以及负载均衡具体的配置,这里只是把最简单易懂的思路说一下)。

所以,我们现在可以

  • 假设北京机房1应用程序或数据库对应的机器停电了,那么我们可以调整负载均衡是原本属于这个机房的用户流量转移到机房2去,注意这里不要有疑问,将用户进行分组是为了防止用户同时写两个数据库发生冲突,那么现在机房1里其实已经不能写入数据了,所以将流量迁移到机房2是没有问题的。
  • 假设北京机房1整个停电了,那么可以通过运营商网络或CDN将流量迁移到北京机房2。
  • 假设北京停电了,那么一样可以将流量迁移到上海。

这个架构中最重要的其实就是用户分组,所以包括我们的应用程序、数据库负载均衡、数据库分表等等都需要按用户进行分组,我们要保证针对同一个用户的请求与操作都在同一个机房内,不去跨机房,这样才是最快的,这就是单元化

那么上面这个架构实际上就是一个高级版的“两地三中心”,只是这种单元化架构我们可以任意去扩展(只要你足够有钱,因为搭一套全配置的数据中心是需要很高成本的),比如你在上海在增加一个数据中心,在杭州也增加一个,那么就如下图:


image.png
image.png

这就叫三地五中心。



 
 
 
 

专访阿里巴巴毕玄:异地多活数据中心项目的来龙去脉

大数据时代,数据中心的异地容灾变得非常重要。在去年双十一之前,阿里巴巴上线了数据中心异地双活项目。InfoQ 就该项目采访了阿里巴巴的林昊(花名毕玄)。

毕玄是阿里巴巴技术保障部的研究员,负责性能容量架构。数据中心异地多活项目就是他主导的。

InfoQ:首先请介绍一下数据中心异地多活这个项目。

毕玄:这个项目在我们内部的另外一个名字叫做单元化,双活是它的第二个阶段,多活是第三个阶段。所以我们把这个项目分成三年来实现。所谓异地多活,故名思义,就是在不同地点的数据中心起多个我们的交易,并且每个地点的那个交易都是用来支撑流量的。

InfoQ:当时为什么要做这件事呢?

毕玄:其实我们大概在 2009 还是 2010 年左右的时候,就开始尝试在异地去做一个数据中心,把我们的业务放过去。更早之前,我们做过同城,就是在同一个城市建多个数据中心,应用部署在多个数据中心里面。同城的好处就是,如果同城的任何一个机房挂掉了,另外一个机房都可以接管。

做到这个以后,我们就在想,异地是不是也能做到这样?

整个业界传统的做法,异地是用来做一个冷备份的,等这边另外一个城市全部挂掉了,才会切过去。我们当时也是按照这个方式去尝试的,尝试了一年左右,我们觉得冷备的方向对我们来讲有两个问题:第一个问题是成本太高。我们需要备份全站,而整个阿里巴巴网站,包括淘宝、天猫、聚划算等等,所有加起来,是一个非常大的量,备份成本非常高。第二个问题是,冷备并不是一直在跑流量的,所以有个问题,一旦真的出问题了,未必敢切过去。因为不知道切过去到底能不能起来,而且整个冷备恢复起来要花多长时间,也不敢保证。因此在尝试之后,我们发现这个方向对我们而言并不好。

那为什么我们最后下定决心去做异地多活呢?

最关键的原因是,我们在 2013 年左右碰到了几个问题。首先,阿里巴巴的机房不仅仅给电商用,我们有电商,有物流,有云,有大数据,所有业务共用机房。随着各种业务规模的不断增长,单个城市可能很难容纳下我们,所以我们面临的问题是,一定需要去不同的城市建设我们的数据中心。其次是我们的伸缩规模的问题。整个淘宝的量,交易量不断攀升,每年的双十一大家都看到了,增长非常快。而我们的架构更多还是在 2009 年以前确定的一套架构,要不断的加机器,这套架构会面临风险。

如果能够做到异地部署,就可以把伸缩规模缩小。虽然原来就是一套巨大的分布式应用,但是其实可以认为是一个集群,然后不断的加机器。但是在这种情况下,随着不断加机器,最终在整个分布式体系中,一定会有一个点是会出现风险的,会再次到达瓶颈,那时就无法解决了。

这两个问题让我们下定决心去做异地多活这个项目。

为什么我们之前那么纠结呢?因为整个业界还没有可供参考的异地多活实现,这就意味着我们必须完全靠自己摸索。而且相对来讲,它的风险以及周期可能也是比较大的。

InfoQ:这个项目具体是怎样部署的?

毕玄:以去年双十一为例,当时我们在杭州有一个数据中心,在另外一个城市还有个数据中心,一共是两个,分别承担 50% 用户的流量。就是有 50% 的用户会进入杭州,另外 50% 会进入到另外一个城市。当用户进入以后,比如说在淘宝上看商品,浏览商品,搜索、下单、放进购物车等等操作,还包括写数据库,就都是在所进入的那个数据中心中完成的,而不需要跨数据中心。

InfoQ:这样的优势是?

毕玄:异地部署,从整个业界的做法上来讲,主要有几家公司,比如 Google、Facebook,这两家是比较典型的,Google 做到了全球多个数据中心,都是多活的。但是 Google 具体怎么做的,也没有多少人了解。另外一家就是 Facebook,我们相对更了解一些,Facebook 在做多个数据中心时,比如说美国和欧洲两个数据中心,确实都在支撑流量。但是欧洲的用户有可能需要访问美国的数据中心,当出现这种状况时,整个用户体验不是很好。

国内的情况,我们知道的像银行,还有其他一些行业,倾向于做异地灾备。银行一般都会有两地,一个地方是热点,另一个地方是冷备。当遇到故障时,就没有办法做出决定,到底要不要切到灾备数据中心,他们会碰到我们以前摸索时所面对的问题,就是不确定切换过程到底要多久,灾备中心到底多久才能把流量接管起来。而且接管以后,整个功能是不是都正常,也可能无法确定。

刚才也提到过,冷备的话,我们要备份全站,成本是非常高的。

如果每个地点都是活的,这些数据中心就可以实时承担流量,任何一点出问题,都可以直接切掉,由另外一点直接接管。相对冷备而言,这是一套可以运行的模式,而且风险非常低。

InfoQ:不过这样的话,平时要预留出很多流量才能保证?

毕玄:没错。因为在异地或同城建多个数据中心时,建设过程中一定都会保有一定的冗余量。因为要考虑其他数据中心出现故障时加以接管。不过随着数据中心建设的增多,这个成本是可以控制的。如果有两个异地的数据中心,冗余量可能是一倍,因为要接管全量。但是如果有三个数据中心,互为备份,就不需要冗余两倍了。

InfoQ:这个项目挑战还是比较大的。您可以介绍一下研发过程中遇到的挑战吗?又是怎样克服的?

毕玄:对于我们来讲,异地项目最大的挑战是延时。跨城市一定会有延时的问题。在中国范围内,延时可能在一百毫秒以内。

看起来单次好像没什么,但是像淘宝是个很大的分布式系统,一次页面的展现,背后的交互次数可能在一两百次。如果这一两百次全部是跨城市做的,整个响应时间会增加很多,所以延时带来的挑战非常大。

在解决挑战的过程中,我们会面临更细节的一些问题。怎样降低延时的影响,我们能想到的最简单、最好的办法,就是让操作全部在同一机房内完成,那就不存在延时的挑战了。所以最关键的问题,就是怎样让所有操作在一个机房内完成。这就是单元化。

为什么叫单元化,而没有叫其他名字呢?原因在于,要在异地部署我们的网站,首先要做一个决定。比如说,冷备是把整个站全部备过去,这样可以确保可以全部接管。但是多活的情况下,要考虑成本,所以不能部署全站。

整个淘宝的业务非常丰富,其实有很多非交易类型的应用,这些功能可能大家平时用的不算很多。但对我们来讲,又是不能缺失的。这部分流量可能相对很小。如果这些应用也全国到处部署,冗余量就太大了。所以我们需要在异地部署的是流量会爆发式增长的,流量很大的那部分。虽然有冗余,但是因为流量会爆发式增长,成本比较好平衡。异地部署,我们要在成本之间找到一个平衡点。所以我们决定在异地只部署跟买家交易相关的核心业务,确保一个买家在淘宝上浏览商品,一直到买完东西的全过程都可以完成。

其他一些功能就会缺失,所以我们在异地部署的并非全站,而是一组业务,这组业务就成为单元。比如说我们现在做的就是交易单元。

这时淘宝会面临一个比 Google、Facebook 等公司更大的一个挑战。像 Facebook 目前做的全球化数据中心,因为 Facebook 更多的是用户和用户之间发消息,属于社交领域。但淘宝是电商领域,对数据的一致性要求非常高,延时要求也非常高。

还有个更大的挑战,那就是淘宝的数据。如果要把用户操作封闭在一个单元内完成,最关键的是数据。跟冷备相比,异地多活最大的风险在于,它的数据会同时在多个地方写,冷备则不存在数据会写错的问题。如果多个地方在写同一行数据,那就没有办法判断哪条数据是正确的。在某个点,必须确保单行的数据在一个地方写,绝对不能在多个地方写。

为了做到这一点,必须确定数据的维度。如果数据只有一个维度,就像 Facebook 的数据,可以认为只有一个纬度,就是用户。但是像淘宝,如果要在淘宝上买一个东西,除了用户本身的信息以外,还会看到所有商品的数据、所有卖家的数据,面对的是买家、卖家和商品三个维度。这时就必须做出一个选择,到底用哪个维度作为我们唯一的一个封闭的维度。

单元化时,走向异地的就是买家的核心链路,所以我们选择了买家这个维度。但是这样自然会带来一个问题,因为我们有三个维度的数据,当操作卖家商品数据时,就无法封闭了,因为这时一定会出现需要集中到一个点去写的现象。

从我们的角度看,目前实现整个单元化项目最大的几个难点是:

第一个是路由的一致性。因为我们是按买家维度来切分数据的,就是数据会封闭在不同的单元里。这时就要确保,这个买家相关的数据在写的时候,一定是要写在那个单元里,而不能在另外一个单元,否则就会出现同一行数据在两个地方写的现象。所以这时一定要保证,一个用户进到淘宝,要通过一个路由规则来决定这个用户去哪里。这个用户进来以后,到了前端的一组 Web 页面,而 Web 页面背后还要访问很多后端服务,服务又要访问数据库,所以最关键的是要保障这个用户从进来一直到访问服务,到访问数据库,全链路的路由规则都是完全一致的。如果说某个用户本来应该进 A 城市的数据中心,但是却因为路由错误,进入了 B 城市,那看到的数据就是错的了。造成的结果,可能是用户看到的购买列表是空的,这是不能接受的。所以如何保障路由的一致性,非常关键。

第二个是挑战是数据的延时问题。因为是异地部署,我们需要同步卖家的数据、商品的数据。如果同步的延时太长,就会影响用户体验。我们能接受的范围是有限的,如果是 10 秒、30 秒,用户就会感知到。比如说卖家改了一个价格,改了一个库存,而用户隔了很久才看到,这对买家和卖家都是伤害。所以我们能接受的延时必须要做到一秒内,即在全国的范围内,都必须做到一秒内把数据同步完。当时所有的开源方案,或者公开的方案,包括 MySQL 自己的主备等,其实都不可能做到一秒内,所以数据延时是我们当时面临的第二个挑战。

第三个挑战,在所有的异地项目中,虽然冷备成本很高,多活可以降低成本,但是为什么大家更喜欢冷备,而不喜欢多活呢?因为数据的正确性很难保证。数据在多点同时写的时候,一定不能写错。因为数据故障跟业务故障还不一样,跟应用层故障不一样。如果应用出故障了,可能就是用户不能访问。但是如果数据写错了,对用户来说,就彻底乱了。而且这个故障是无法恢复的,因为无法确定到底那里写的才是对的。所以在所有的异地多活项目中,最重要的是保障某个点写进去的数据一定是正确的。这是最大的挑战,也是我们在设计整个方案中的第一原则。业务这一层出故障我们都可以接受,但是不能接受数据故障。

还有一个挑战是数据的一致性。多个单元之间一定会有数据同步。一方面,每个单元都需要卖家的数据、商品的数据;另一方面,我们的单元不是全量业务,那一定会有业务需要这个单元,比如说买家在这个单元下了一笔定单,而其他业务有可能也是需要这笔数据,否则可能操作不了,所以需要同步该数据。所以怎样确保每个单元之间的商品、卖家的数据是一致的,然后买家数据中心和单元是一致的,这是非常关键的。

这几个挑战可能是整个异地多活项目中最复杂的。另外还有一点,淘宝目前还是一个高速发展的业务,在这样的过程中,去做一次比较纯技术的改造,怎样确保对业务的影响最小,也是一个挑战。

InfoQ:要将延时控制在 1 秒之内,网络和硬件方面都有哪些工作?

毕玄:如果网络带宽质量不好,1 秒是不可能做到的。我们在每个城市的数据中心之间,会以一个点做成自己的骨干网,所以可以保障不同城市之间的网络质量。但是要保证到 1 秒,还必须自己再去做东西来实现数据的同步,这个很关键。这个东西现在也在阿里云上有开放了。

InfoQ:异地多活其实也是实现高可用。阿里技术保障的梁耀斌(花名追源)老师会在4 月23 日~25 日的 QCon 北京 2015 大会上分享《你的网站是高可用的吗?》,因为当时的题目和内容也是您参与拟定的。您可以先谈一下其中的一些标准吗?

毕玄:其实每家比较大的互联网公司,每年可能都会对外公开说,我们今年的可用性做到了多少,比如 4 个 9 或者 5 个 9。但是每家公司对可用性的定义可能并不一样。比如说,有的公司可能认为业务响应时间超过多少才叫可用性损失,而其他公司可能认为业务受损多少就是可用性损失。

我们希望大家以后有一个统一的定义,这样就比较好比较了。我们发现,真正所有做到高可用的网站,最重要的一点是故障恢复时间的控制。因为出故障是不可避免的,整个网站一定会出现各种各样的故障,关键是在故障出现以后,应对能力有多强,恢复时间可以做到多短。追源会在 QCon 上分享,我们在应对不同类型的故障时,我们是怎样去恢复的,恢复时间能控制到多短,为什么能控制到那么短。在不同的技术能力,以及不同的技术设施的情况下,能做到的恢复时间可能是不一样的,所以我们会定义一个在不同的技术能力和不同的技术设施的情况下,恢复时间的标准。如果恢复时间能控制得非常好,可能整个故障控制力就非常强。举个例子,比如淘宝因为能够做到异地多活,并且流量是可以随时切换的,所以对于我们来讲,如果一地出现故障,不管是什么原因,最容易的解决方案,就是把这一地的流量全部切走。这样可以把故障控制在一分钟以内,整个可用性是非常高的。

关于系统的容灾能力,国家也有一个标准,最重要的一点就是故障的恢复时间。如果大家都以故障恢复时间控制到哪个级别来衡量,那所有网站就有了一套标准。

 
 

蚂蚁金服三地五中心异地多活解决方案是基于完全自主研发的SOFA金融分布式架构及OceanBase关系数据库。

在该方案中,SOFA分布式架构能够承受高并发交易,并确保资金安全;同时,在系统扩展、容灾恢复、更新发布时做到数据无损,且服务持续可用。OceanBase分布式关系数据库具备数据强一致、高可用、高性能、在线扩展、高度兼容SQL标准和主流关系数据库、低成本等特点;可在低成本的通用硬件上,进行在线水平扩展,并创造了4200万次/秒处理峰值的纪录

 
原文地址:https://www.cnblogs.com/xuwc/p/13429614.html