持续可用和快速容灾切换的能力,是技术人员追求的极致目标。在架构设计中,容灾设计强调的是系统对外界环境影响具备快速响应能力,节点级别的快速恢复能力,保障系统的持续可用。
去年12月18日,全球架构师峰会上,阿里巴巴高级系统工程师曾欢(善衡)结合互联网金融业务及系统特性,分享了在支付宝系统架构演进中,每个阶段的高可用和容灾能力建设的解决思路。
在架构设计中,作为系统高可用性技术的重要组成部分,容灾设计强调的是系统对外界环境影响具备快速响应能力,尤其是当发生灾难性事件并对IDC节点产生影响时,能够具备节点级别的快速恢复能力,保障系统的持续可用。2015年12月18日,年度高端技术盛会:“全球架构师峰会——ArchSummit”在北京国际会议中心隆重召开,会上,阿里巴巴高级系统工程师:善衡(曾欢)结合互联网金融业务及系统特性,分享了在支付宝系统架构演进中,每个阶段的高可用和容灾能力建设的解决思路。本文由其演讲内容整理而成。
支付宝的系统架构,其发展历程可以分为清晰的3个阶段,每一个阶段都有自己独特的特点和架构上相应的痛点。在每一个阶段的发展过程中,支付宝的技术人员针对不同的问题进行诸多的思考,在解决这些问题的过程中也做了诸多的尝试。
在此阶段,支付宝的系统架构相对比较简化,如图1所示,通过商用LB让用户的流量进到入口网关系统,支付宝的系统服务暴露也通过商用设备挂在VIP下,每个提供服务的应用机器通过VIP来进行负载均衡。早期支付宝的核心系统库都在一个数据库上(后期拆为多个数据库),即每个核心系统都只用单独的数据库。在这样一个“物理上多机房,逻辑上单机房”的架构背后,每天的业务量仅仅为数十万级,应用系统也只有数十个,容灾能力相对较低:例如单应用出现问题时无法及时有效地切换、主机和备用机进行切换时,一定程度上会导致业务中断,甚至有时会有不得不进行停机维护的情况,使得整个系统面对数据故障时显得十分被动。
我对“物理上多机房,逻辑上单机房”的理解是,交易库和财务库都是单库,所以虽然两个库可以分布在不同的机房,但是只要有一个机房出问题,整个系统就不可用了。
随着业务量的不断增长,该架构发展到2011年,出现了一些比较典型的问题。如下图所示:由于系统内部使用的都是LB设备,商用LB的瓶颈就尤其明显,由于业务的发展累计,VIP及其上面发布的服务越堆越多,设备如果出现抖动或者宕机会对业务造成严重影响,这即是架构上的单点。第二个问题就是数据库的单点瓶颈。随着业务量的不断增加,单一的核心数据库一旦出现异常,比如硬件故障、负载异常等等,进而会导致整个核心链路上的业务都不可用。
- LB是一个单点问题和瓶颈;
- 单库是一个单点问题和瓶颈;
如何消除系统架构当中存在的单点问题,优雅解决未来1-3年之间业务量增长(数百万级/天)和机器数量增长(数百个系统),是首先要解决的问题,于是带来了下一代架构革新。
鉴于第一阶段支付宝碰到的这些痛点,在第二个阶段,它将逻辑上的单个机房拆分成为多个机房,通过把硬负载转换成为软负载,以实现分布式的服务调用,如下图所示。下图为基于常见的消费者和生产者模型来构建的业务模型,其中配置中心负责服务注册以及对应服务提供方可用状态变化的通知,从而将信息实时推送到消费方的订阅关系上。值得注意的是,支付宝对原有架构做了一个较大的改进:它将普通的一体化配置中心分拆成两个模块,一个Session模块,用于管理消费者和生产者的长连接保持;一个Data模块,用于注册服务时存储相关。通过这两个模块的深度解耦,进一步提高整个配置中心的性能。
除此之外,支付宝还做了数据的水平扩展。其实早在2011年之前,支付宝就已经开始从事此项工作,根据用户的UID,将一个交易库水平拆分为多个库,如下图所示。在此期间,需要解决的问题就是“对应用透明”,如何通过“应用无感知”的方式进行用户数据库的拆分,是水平扩展实施时首先要考虑的;其次,如何通过一个数据中间件来管理数据分片的规则,也是数据水平扩展过程中的关键问题。
通过上述两个比较典型的优化,支付宝的整个系统架构如图5所示。从应用层面上来说每个机房都是一个节点;从数据层面上,每个机房有特定的几个数据分片在里面。在部署模式上,当支付宝扩张到3个或4个机房的时候,需要全局考虑数据分片部署,每个机房都有可能不可用,这些备库们应当分散到不同的多个机房里面,从而达到多机房备灾的目的。
这种多机房多活的第二代架构体系,其优势在于:
虽然在此过程中自然解决了上述的单点问题,但仍存在一个问题没有解决。即数据库日常维护时,或因为硬件的故障导致数据库宕机时,支付宝需要进行主备切换,在此过程中业务是有损的状态。一般情况下当IDC出现问题的时候,工程师们会通过前端的流量管控系统先把用户的流量从出现异常的机房切换到正常的机房中,然后进行数据库的主备切换,即将备用负载替换主用负载。
在这个过程中,有两个比较大的痛点:
一旦数据库发生故障,我们需要进行主备切换时,因为切换过程中的数据不可写,部分用户操作后的状态不对,对用户来说是会担心的。为了解决这个问题,我们制定了一个Failover方案。该方案主要通过业务层进行改造,例如针对流水型的业务数据,我们是这么来做的:正常进行数据流量存取的时候,只有主库提供路线服务,主库和备库之间进行正常的数据同步,但是Failover库不进行数据同步,正常状态下对业务系统不可见。即正常情况下,没有数据流经过Failover库,而且Failover库是空的,没有任何历史数据,如下图所示:
一旦故障发生,主库发生宕机,支付宝人员将通过容灾切换将所有数据的读写放置在FailOver数据层中进行。因为是实时流水型的数据,所以不会对历史数据产生任何依赖和影响。切换完成后,整个核心链路上的业务就已经全面恢复起来了。通过这种方式,使得支付宝可以将数据库在短短5分钟内进行切换,一旦故障解除,随时可以将数据读写重新切换到主存储库上来。
在进行主备切换的时候系统不能正常地提供服务;这个时候切换到FailOver库进行读写,以正常提供服务;等主备切换完成,可以将FailOver库中的数据完完整整地拷贝到主库和备库。
FailOver方案上线后,支付宝基本上所有的核心业务都基于此进行了方案改造,并针对不同的业务(不仅限于应用层)都会有不同的FailOver方案。现在,支付宝在原有的方案基础上再多准备一个Failover数据库(如图8中蓝色图形所示),与之前提到的容灾设计一样,如果需要进一步保证Failover库的可用性,还可以增加Failover库的备库。此外Failover库需要与主库分开,可以与主库、备库都不放在同一个机房。
通过“多机房多活”的架构改造以及FailOver方案的实施,满以为未来三年都无需为IDC资源去发愁的支付宝研发团队,在顺利支撑完2012年的“双11”,为下一年做规划时却发现梦想破灭了。因为他们遇到了严峻的新问题:
新的问题进而带来对新一代架构的要求:
单元化的核心思想包括核心剥离以及长尾独立。核心剥离指的是将核心业务进行剥离;将业务数据按照UserID进行拆分,从而实现多机房部署;在此基础上将每一个机房的调用进行封闭式设置;每一个单元中的业务数据无需和其它单元进行同步。长尾独立则针对非核心的应用,这些业务数据并不按照UID进行拆分,核心业务并不依赖于长尾应用。
支付宝单元化架构实现的主要思想有两点,如下图所示:
支付宝单元化架构于2013年完成,帮助支付宝顺利支撑过了2013年的“双11”。而2014年~2015年,支付宝一直在尝试解决异地延时的问题:即如果不去对全局数据进行分割或是本地化的话,当把业务单元搬到异地时,由于每一次业务的发生基本上都会依赖全局数据,且会对应多次数据访问,而每一次数据访问都会产生异地所带来的延时,积少成多,时间延迟就会达到秒级,用户体验大幅度下降。基于这个问题的考虑,支付宝研发团队做了一个很大的决定:他们引入了单元C,通过将无法拆分的全量数据进行全局复制(异地机房之间的复制),以便于支撑核心业务本地调用,进而实现读写分离,将跨城市的调用减少到最小力度。如下图所示。
由于数据的写入操作会在每一个数据单元上进行,而单元C的数据读取是要求全量的,所以进行这一项改造的时候需要底层的支持,从而解决架构改造时数据一致性和时效性的问题。为了解决这个问题,支付宝团队提出了两种解决方案:
通过本地化调用,支付宝有效地解决了DB连接数问题、机房间流量限制问题、跨IDC的延时问题;通过异地的单元部署以及不断的容灾演练和数据切换,支付宝有效地解决了城市IDC资源限制和异地IDC容灾问题。另外还有一个诉求——“蓝绿发布”,支付宝是这么实现的。
如下图所示,蓝绿发布即每个单元里面分为一个Blue组和一个Green组,日常模式下两个组各承担50%的用户流量;发布前将Green组中的50%流量移到Blue组中,然后对Green进行两批无序发布;新代码发布上去后,将Blue组中的流量先切换1%~2%到Green组中进行验证,以最大程度减少对用户的打扰,验证完毕后,再逐步将100%的流量全部切换至新的Green组,重复前面的步骤发布Blue组,验证完毕后切回每个组各50%流量的日常模式。
至此,支付宝单元化全局架构如下图所示。每一个机房单元中有单元A和单元C,单元A中按逻辑分为了两个组(蓝绿),单元C之间进行全局的数据复制;每个单元中部署了一套分布式的容灾管控系统,使得支付宝能在单个机房故障的时候去做更加快速的应对。
单元B放置无法拆分的历史业务,例如某些不重要的业务等
通过单元化的系统配置,使得支付宝整个系统架构具有很强的高可用性和容灾能力。具体来说有三点: