当前位置: 首页 > 科技观察

支付宝架构有多牛逼?还没看完就跪了...

时间:2023-03-20 12:24:15 科技观察

图片来自抱图网。峰值,每秒58.3万笔交易,同样是新的峰值交易记录,但与往年相比,翻了一番,增长了30%到40%,增速还是小了很多。2010年双十一的支付峰值是2万笔/分钟,到2017年双11变成了25.6万笔/秒,去年是58.3万笔/秒,是首届双11的千倍以上2009年11.为了承受这么大的支付TPS,蚂蚁做了大量的顶层架构设计和底层优化,其中最核心的就是LDC架构。LDC的全称:LogicDataCenter,逻辑数据中心,之所以叫LDC,是相对于传统的IDC(InternetDataCenter)提出的一个概念。IDC相信大家都很清楚,它是一个物理数据中心。说白了就是可以建网站的物理机房。LDC(LogicalDataCenter),核心架构思想是无论你的物理机房怎么部署,比如你可能有3个IDC,分别位于两个不同的城市(常说的两地三中心),它们在逻辑上是统一的。我从逻辑上看是一个整体,统一协调部署。为什么LDCLDC的出现解决了哪些问题?我们必须从架构的演变开始。之前我们讲过机房容灾设计的架构演进,我们就结合一个具体的应用来推演一次。首先看下图所示的单体应用架构。请求到网关接口,网关接口直接调用应用或服务,服务调用存储层查询或写入数据。这种架构模式最大的风险是服务和存储是单点的。访问容量和性能受限于存储和应用程序的容量和性能。在容灾方面,一旦发生故障,只能等待单点应用或存储的恢复。.后来工程师开始横向拆分应用,纵向拆分服务。水平拆分大家应该不陌生,就是增加服务器,在每台服务器上部署实例,垂直拆分就是按域拆分服务。比如一个交易系统,包括商户域、产品域、用户域、订单域等,拆分成多个微服务,服务解耦,服务可以独立发布,应用的复杂度会更高。这种分布式架构解决了单点服务的问题。如果一台服务器宕机了,服务还是可以的,但是存储层还是单点的,而且随着业务的增长,扩容加入的机器越多,大家发现查询写入效率需要时间才能达到到某个阶段,速度变慢,分析表明存储层存在性能瓶颈。上图中只用了2台服务器连接数据库。在一个真正的分布式系统中,可能有几十台甚至上千台服务器。如果全部连接到一个DB,连接数、锁争用等问题都会降低SQL性能。知道。后来的事情大家都知道了。互联网公司开始读和写分离,把读请求和写请求分开。读写分离隐含了一个逻辑,就是数据写入后,不会立即使用。正在写入的数据和立即使用的数据之间存在时间间隔。直到数据从数据库中同步出来后才会读取数据。实际统计表明,在常规应用中,90%的数据写入后不会立即使用。当然,我这里说的即时时间单位是ms,一般的同步延时都是几毫秒,不会超过10~20ms。但是这种架构并没有解决写的问题。随着业务量的增长,写入数据成为瓶颈。分库分表应运而生,分库分表的中间件开始流行,现在基本已经成为中大型互联网公司的标配。基本思想是按照指定的维度对数据进行拆分。更常见的是userId维度。比如取userId的后2位可以分出几百个库和表,有的可以除以指定的模取余数,比如除以64得到余数可以分出64个库根据余数范围0-63。关于分库分表,很多人都知道有垂直拆分和水平拆分两种(上面说的垂直和水平是系统的拆分,这里指的是存储)。垂直拆分是按照业务维度拆分,将相同业务类型的表放到一个库中,往往按照领域模型的概念进行拆分,比如订单库、用户库、商品库等。水平拆分是将一个将数据量大的表(库)合并成许多数据量小的表(库),以减轻库和表的访问压力。可以类比为系统的横向和纵向拆分:为什么叫横向和纵向?其实,很容易理解。你想象一个用户表,里面有很多字段,如下图所示:垂直拆分就是从中间垂直画一把刀,把右边蓝色的用户信息表和绿色的订单信息表组合在一起。拆分成2个表。库分为用户库和订单库。水平拆分就是做水平切分,减少数据量。看到这里,是不是觉得问题已经解决了呢?经过上面的分库分表,如果应用层面能搞定的话,数据库层面确实可以做到万并发的水平。但是再增加一个数量级的容量就有点困难了。为什么?因为一个库实例是所有应用共享的,即每增加一台机器,数据库连接就会相应增加,增量至少是机器设置的最小连接数。为什么应用程序需要连接到所有数据库实例?答:网关层的流量可能到任何一台服务器。例如,用户A的请求到达了服务器。此时服务器必须有用户A的userId分片的数据库连接,否则流量会被路由走,或者执行失败。分库分表只是解决了单库单表的访问压力问题,但是由于每台服务器同时连接了所有的分库实例,所以到一定阶段就没有进一步扩容了,因为有瓶颈是数据库实例的连接数。数据库瓶颈如何处理?相信聪明的已经猜到了,就是在应用层根据userId分片做隔离,在流量路由的时候将指定uid分片的流量路由到指定的应用单元执行网关层。内部消化了这个应用单元的流量,如下图:比如uid=37487834,最后两位是34,属于00-49范围,那么用户流量直接路由到应用00-49组,所有数据交互都在本单元操作完成。这样,uid00-49分组单元中的应用只使用userId00-49分库连接的数据库,uid50-99分组单元的应用也是如此。数据库的连接数直接减半,而且还可以拆分单元,现在是2个单元,最多可以拆分100个单元。这里我强调单位这个词,因为这是LDC中的核心概念。让我重点谈谈单位这个词的具体含义。Ant中的单元有一个名字叫做Zone,完整的服务部署在Zone中。例如,一个用户可以在一个区域完成一套完整的业务流程,流量不需要其他区域提供服务。具有完成一套完整服务的能力,单个zone可以完成一套完整的服务,逻辑上是自成体系的。这样做有什么好处?如果一个zone发生故障,路由层会直接将该zone的流量转移到其他zone,其他接收到该zone流量的zone可以共享流量,非常方便流量分配。下图是AntZone按照region和userId分片的部署架构示意图。进行了一些简化。实际的Zone部署单元会稍微复杂一些。上面介绍的Zone能够在uid维度完成一套完整的业务流程。应用程序相互依赖的服务均由该Zone提供,服务之间的调用均在该Zone内完成。但是如果你聪明的话,你可能会想到一个问题。部分数据无法按照userid维度进行拆分。如果全局只有一份怎么办。例如,配置中心的数据集中存储。全局只有一种配置。.其实在Ant内部,一共有三种Zone:RZone:上面说的逻辑是自包含的,是业务系统整体部署的最小单元,可以按照userId维度拆分的服务和库是部署在RZone中。GZone:它是一个全局区域。看名字就知道全球只会部署一份GZone的服务和库。一定是在某个机房,也会部署在其他地方,但是只是为了容灾,不会启用。CZone:有趣。为什么会有CZone?它的创建是为了解决GZone的缺点。由于距离远,跨城市通话需要很长时间。如果GZone的服务部署在上海,杭州机房的服务需要GZone部署。服务只能跨城市、跨机房调用。很可能一个服务有很多RPC调用,那么耗时肯定会爆炸,那怎么办呢?搭建城市之间的数据同步桥梁,CZone扮演桥梁的角色,负责GZone在城市之间的数据同步之前,C的意思是city。也是因为我前面提到的“读写时差现象”,写入GZone的数据允许有一定的延迟,同步CZone同步到其他CZone。作者:Angela编辑:陶佳龙来源:转自公众号Angela的博客(ID:guofangela)