多机房多活架构

2015年底的时候,到家集团启动了一个"凌云"项目,将所有系统从北京的M6机房迁移到阿里云,完成技术栈"上云"。项目涉及几百台机器,到家所有的业务,所有的系统,需要所有技术部门配合,耗时超过一个季度,是一个不折不扣的大项目。

今天,简单聊聊当时的架构方案,我们是如何平滑进行机房迁移的。

1 被迁移的系统是一个什么样的架构?

被迁移系统架构
上图是一个典型的互联网单机房系统架构:

  • 上游是客户端,PC浏览器或者APP;
  • 然后是站点接入层,做了高可用集群;
  • 接下来是服务层,服务层又分为业务服务层和基础服务层,都做了高可用集群;
  • 底层是数据层,包括缓存和数据库;

该单机房分层架构,所有的应用、服务、数据部署在同一个机房,其架构特点是全连接:

  • 站点层调用业务层,业务服务复制了多少份,上层就要连接多少个服务;
  • 业务服务层调用基础服务层,基础服务层服务了多少份,上层就要连多少个服务;
  • 服务层调用数据库,数据库冗余了多少份,就要连多少个数据库;
    例如:站点接入层某一应用有2台机器,业务服务层某一个服务有4台机器,那肯定是上游的2台会与下游的4台全连接;

全连接如何保证系统的负载均衡和高可用?
全连接架构的负载均衡和高可用保证,是通过连接池实现的,不管是NG连接web,web连接业务服务,业务服务连接基础服务,服务连接数据库,都是这样。
单机房架构的核心是全连接

2 机房迁移的目标是什么?

单机房架构的特点是“全连接”,机房迁移要做一个什么样的事情呢?
机房迁移
迁移之前,系统部署在机房A(M6)内,是单机房架构;
迁移之后,系统部署在机房B(阿里云),仍然是单机房架构,只是换了一个机房而已;

有什么好的迁移方案?
最容易想到的一个方案:把所有服务在新机房全部都部署一套,然后将流量切过去;

这个方案存在什么问题?
问题1:需要停止服务,丧失了可用性;
问题2:即使可以接受停服,当几百台机器,几千个系统重新部署一套,切换流量,一步成功的概率较低,风险较高;
机房迁移的难点,是平滑迁移,整个过程不停服务,能够蚂蚁搬家式迁移。

机房迁移的设计目标是:

  • 平滑迁移,不停服务;
  • 可以分批迁移;
  • 随时可以回滚;

3 临时性多机房架构能否避免?

如果想要平滑迁移机房,不停服务,且逐步迁移,迁移的过程中,势必存在一个中间过渡阶段,两边机房都有流量,两边机房都对外提供服务,这就是一个多机房的架构。
迁移过程中,多机房架构不可避免。

前文提到的单机房架构,是一个"全连接"架构,能不能直接将单机房的全连架构套用到多机房呢?

如果直接将单机房全连接的架构直接应用到多机房,会导致很多跨机房的连接:

  • 站点层连接业务服务层,一半的请求跨机房;
  • 业务服务层连接基础服务层,一半的请求跨机房;
  • 基础服务层连数据层,一半的请求跨机房;

大量的跨机房连接会带来什么问题?

同机房连接,内网的性能损耗几乎可以忽略不计,一旦涉及到跨机房访问,即使机房和机房之间有专线,访问的时延可能增加到几毫秒,甚至几十毫秒(跟机房间光纤距离有关)。举个例子,用户访问一个页面需要用到很多数据,这些数据可能需要20次相互调用(站点调用服务,服务调用缓存和数据库等),如果有一半调用跨机房(10次调用),机房之间延迟是20毫秒,因为跨机房调用导致的请求迟延就达到了200毫秒,这是绝不能接受的。

想要平滑的实施机房迁移,临时性的多机房架构不可避免。

小结:

  • 单机房架构的核心是全连接。
  • 机房迁移方案的设计目标是:平滑迁移,不停服务,分批迁移,随时可以回滚;
  • 想要平滑的实施机房迁移,临时性的多机房架构不可避免;

4 临时性多机房架构如何实施?

如将单机房全连接架构应用到多机房,会有大量跨机房调用,极大增加请求时延,是业务无法接受的,想降低时延,就必须实施同机房连接。
多机房多活架构,什么是理想状态下的同机房连接?
同机房连接
如上图所示,多机房多活架构,理想状态下除了异步数据同步跨机房通讯,其他所有通讯均为同机房连接:

  • web连业务服务;
  • 业务服务连基础服务;
  • 服务连数据库,主库写,从库读,读写分离;
    上述架构,每个机房是一套独立的系统,仅仅通过异步数据同步获取全量数据,当发生机房故障是,将流量切到另一个机房,就能冗余机房级故障,实现高可用。

上述多机房架构存在什么问题?
异步数据同步存在延时(如1min),这个延时的存在会使得两个机房的数据不一致,从而导致严重的业务问题。举个例子:
某时刻用户X有余额100元,两个机房都存储改余额的精准数据,接下来
(1) 余额100,X在北京(就近访问机房A)消费了80元,余额仅剩20元,该数据在1分钟会同步到机房B;
(2) 余额100,X的朋友在广州(就近访问机房B)用X的账号消费了70元,余额仅剩30元,该数据在1分钟后也会同步到机房A;
从而导致:
(1) 超额消费,100余额,买了150的东西;
(2) 余额异常,余额是20还是30?

上述架构适用于什么业务场景?
任何脱离业务的架构设计都是耍流氓。当每个机房都有很多全局业务数据的访问场景时,上述多机房架构并不适用,会存在大量数据不一致,但当每个机房都访问局部业务数据时,上述多机房架构仍然是可行的,典型的业务有滴滴和快狗打车,这些业务具备数据聚集效应:
(1) 下单用户在同一个城市;
(2) 接单司机在同一个城市;
(3) 交易订单在同一个城市;
这类业务非常适合上述多机房多活架构,多个机房之间即使存在1分钟延时的异步数据同步,对业务也不会造成太大的影响。多机房多活架构,做不到理想状态下的同机房连接,有没有折中方案?
如果完全避免跨机房调用的理想状态做不到,就尽量做到最小化跨机房调用。
伪多机房软件架构
如上图情况,在非必须的情况下,优先连接同机房的站点和服务:
(1) 站点层只连接同机房的业务服务层;
(2) 业务服务层只连接同机房的基础服务层;
(3) 服务层只连接同机房的读库;
(4) 跨机房写库;

该方案没有完全避免跨机房调用,但做到了最小化跨机房调用,只有写请求是跨机房的,但互联网业务绝大部分都是读多写少的业务:
(1) 百度的搜索100%是读业务;
(2) 京东淘宝电商99%的浏览搜索是读业务,只有下单支付是写业务;
(3) 58同城99%帖子的列表详情查看是读业务,只有发布帖子是写业务;

写业务比例相对少,并没有做到100%的同机房连接,通常称之为伪多机房多活架构;伪多机房多活架构,有主机房和从机房的差别。多机房多活的初衷是容机房故障,该架构当出现机房故障时,可以把入口流量切到另一个机房:
(1) 如果挂掉的是,不包含主库的从机房,迁移流量后能直接容错;
(2) 如果挂掉的是,包含主库的主机房,只迁移流量,系统整体99%的读请求可以容错,但1%的写请求会受到影响,此时需要将从库变为主库,才能完全容错,这个过程需要DBA接入,不需要所有业务线上修改。

画外音:除非站点和服务使用内网IP,而不是内网域名连接数据库,架构师之路已经强调过很多次,不要使用内网IP,一定要使用内网域名,这样运维在切换数据库时:

  • 运维修改内网DNS,将内网域名指向新的IP,如果是短连接调用,未来新的请求流量,自然会切到新的IP上;如果是长连接调用,新的长连接会连到新的IP上,但旧的长连接仍然连接的是旧IP;
  • 运维统一将旧IP上的连接切断,如无意外,服务或者数据库的连接池都有重连功能,重连后就会自动连到新IP上去;
    如此这般,只要运维配合就可以完成IP的迁移,对于所有上游的调用方不需要配合修改配置重启,对于IP解耦非常有效;

伪多机房多活架构,是一个实践性,落地性很强的架构,它对原有架构体系的冲击非常小,和单机房架构相比,仅仅是:
(1) 跨机房主从同步数据,会多10毫秒延时;主从同步数据,本来就会有延时;
(2) 跨机房写,会多10毫秒延时;

小结:
(1) 理想多机房多活架构,是纯粹的同机房连接,仅有异步数据同步会跨机房;
(2) 理想多机房多活架构,会有较严重数据一致性问题,仅适用于具备数据聚集效应的业务场景,例如:滴滴,快狗打车;
(3) 伪多机房多活架构,思路是最小化跨机房连接,机房区分主次,落地性强,对原有架构冲击较小,强烈推荐;

5 如何分批平滑上云?

系统架构
如上图,系统分层架构包含:web、业务服务、基础服务、缓存、数据库,都需要迁移;大的方向,有两种方案:
(1) 自底向上的迁移方案,从数据库开始迁移;
(2) 自顶向下的迁移方案,从web开始迁移;
两种方案分别在58同城和58到家实践过,都是平滑的,蚂蚁搬家式的,随时可以回滚,对业务无任何影响,本文重点介绍自顶向下方案。

5.1 站点与服务迁移:无状态,迁移容易

站点和服务迁移
步骤一,前置条件:
(1) 新机房准备就绪;
(2) 专线准备就绪;

步骤二,在新机房搭建好待迁移的子业务,部署好web站点,业务服务,基础服务,做好充分的测试;
这里重点说明的是:
(1) 垂直拆分迁移,每次迁移的范围不要太大,划分好子业务和子系统;
(2) 缓存和数据库还未迁移,存在跨机房连接;
(3) 新机房的配置文件注意同连,不要跨机房调用业务与基础服务;

只要不切流量,依然老机房提供服务,新机房随便操作;

步骤三,灰度切流量,将被迁移的子业务切5%的流量到新机房,观察新机房的站点与服务是否异常,如果没有问题再10%,20%,50%,100%逐步放量,直至某个子业务迁移完成。第一个子业务的站点和服务迁移完成之后,第二个子业务,第三个子业务,直到所有业务把站点和服务都全流量的迁移到新机房。

如何应对异常?
在迁移过程中,任何一个子业务,任何时间发生异常,可以将流量切回旧机房,旧机房的站点、服务、配置都没有改动,依然能提供服务,因此这是一个非常稳的迁移方案。

5.2 缓存迁移:有状态,但数据可重建

站点和服务迁移完成之后,接下来再迁缓存。
缓存迁移
经过第一步的迁移,如上图:
(1) 所有入口流量都已经迁到了新的机房;
(2) 缓存和数据库,仍然使用旧机房;
旧机房的站点和服务不能停,只要旧机房不停,就保留了切回流量回滚的可能性。

步骤四,在新机房搭建好缓存,缓存的规模和体量与旧机房一样;
步骤五,按照子业务垂直逐步切换使用新机房缓存,切换细节为:
(1) 运维做一个缓存内网DNS的切换(内网域名不变,IP切到新机房);
(2) 杀掉原有缓存连接,业务线不需要做任何修改,只需要配合观察业务;
(3) 缓存连接池会自动重连,重连会自动连接新机房的缓存;

这里需要注意几点:
(1) 如果没有使用内网域名,而是采用IP直连缓存,则需要业务配合,换新机房IP重启;
(2) 缓存迁移时间,尽量选在流量低峰期,新缓存是空数据,如果选在流量高峰期,短时间内可能会有大量请求穿透到数据库上;
(3) 对于同一个服务,缓存的切换是瞬时的,不会同时使用新旧机房缓存;
缓存的迁移也是按照子业务垂直拆分,蚂蚁搬家式迁移,整个迁移过程除了运维操作切内网域名,研发和测试都只是配合观察服务,风险较低;缓存允许cache miss,不用转移旧缓存内数据。

5.3 数据库迁移:有状态,数据也要迁移

站点层、服务层、缓存层都迁移之后,最后是数据库的迁移。
数据库迁移
在迁移数据库之前,服务通过专线跨机房连接数据库。

如何迁移数据库?
步骤六,现在新机房搭建新的数据库;
步骤七,数据同步,自建机房可以使用数据库MM/MS架构同步数据,阿里云可以使用DTS同步数据;
数据库同步完之后,如何进行数据源切换?
能否像缓存的迁移一样,运维修改一个数据库内网DNS指向,然后切断数据库连接,让服务重连新的数据库?这样业务不需要改动,也不需要重启,此种方式看上去不错,但是:
(1) 一定要保证数据库同步完成,才能切流量,但数据同步总是有延迟的,旧机房一直在不停的写数据;
(2) 只有域名和端口不发生变化,才能不修改配置完成切换,但如果域名和端口(主要是端口)发生变化,是做不到不修改配置和重启的,例如原有数据库端口使用了5858,而阿里云要求你是用3200,就必须改端口重启;

步骤八,最终的方案是,DBA在旧机房的数据库设置一个ReadOnly,停止数据的写入,在秒级别RDS同步完成之后,服务修改数据库端口,重启连接新机房的数据库,完成数据层的切换。这一过程中为了保证数据的一致性,会损失秒级别的写入可用性。
迁移完成
经过上述站点、服务、缓存、数据库的迁移,上云目标平滑完成。

5.4 自顶向下的机房迁移方案总结

先迁移站点层、业务服务层和基础服务层
(1) 准备新机房与专线;
(2) 搭建集群,充分测试,子业务垂直拆分迁移;
(3) 灰度切流量;

缓存层迁移
(4) 搭建新缓存;
(5) 运维修改缓存内网DNS,切断旧缓存连接,重连新缓存,切流量;

数据库迁移
(6) 搭建新数据库;
(7) 同步数据;
(8) 旧库ReadOnly,同步完成后(秒级),服务指向新库,改配置重启,切流量;

以上8大步骤,整个过程分批迁移,一个子业务一个子业务的迁移,一块缓存一块缓存的迁移,一个数据库一个数据库的迁移,任何步骤出现问题都可以回滚的,整个过程不停服务。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至yj.mapple@gmail.com

文章标题:多机房多活架构

文章字数:4.4k

本文作者:melonshell

发布时间:2020-01-24, 10:47:24

最后更新:2020-01-26, 16:29:53

原始链接:http://melonshell.github.io/2020/01/24/tech3_multi_room_living/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏

相册