支付宝架构
支付宝架构
1. 支付宝架构理论
自 2008 年双 11 以来,在每年双 11 超大规模流量的冲击上,蚂蚁金服都会不断突破现有技术的极限。2010 年双 11 的支付峰值为 2 万笔/分钟,到 2017 年双 11 时这个数字变为了 25.6 万笔/秒。
- 支付宝海量支付背后最解渴的设计是啥?换句话说,实现支付宝高 TPS 的最关键的设计是啥?
因为数据库存储层瓶颈的存在再多水平扩展的服务器都无法绕开,而从整个互联网的视角看,全世界电商的交易 TPS 可以轻松上亿。
这个例子带给我们一些思考:为啥几家互联网公司的 TPS 之和可以那么大,服务的用户数规模也极为吓人,而单个互联网公司的 TPS 却很难提升?
究其本质,每家互联网公司都是一个独立的大型单元,他们各自服务自己的用户互不干扰。
这就是单元化的基本特性,任何一家互联网公司,其想要成倍的扩大自己系统的服务能力,都必然会走向单元化之路。
它的本质是分治,我们把广大的用户分为若干部分,同时把系统复制多份,每一份都独立部署,每一份系统都服务特定的一群用户。
以淘宝举例,这样之后,就会有很多个淘宝系统分别为不同的用户服务,每个淘宝系统都做到十万 TPS 的话,N 个这样的系统就可以轻松做到 N*十万的 TPS 了。
LDC 实现的关键就在于单元化系统架构设计,所以在蚂蚁内部,LDC 和单元化是不分家的,这也是很多同学比较困扰的地方,看似没啥关系,实则是单元化体系设计成就了 LDC。
小结:分库分表解决的最大痛点是数据库单点瓶颈,这个瓶颈的产生是由现代二进制数据存储体系决定的(即 I/O 速度)。
单元化只是分库分表后系统部署的一种方式,这种部署模式在灾备方面也发挥了极大的优势。
蚂蚁单元化架构实践
蚂蚁支付宝应该是国内最大的支付工具,其在双 11 等活动日当日的支付 TPS 可达几十万级,未来这个数字可能会更大,这决定了蚂蚁单元化架构从容量要求上看必然从单机房走向多机房。
另一方面,异地灾备也决定了这些 IDC 机房必须是异地部署的。整体上支付宝也采用了三地五中心(IDC 机房)来保障系统的可用性。
跟上文中描述的有所不同的是,支付宝将单元分成了三类(也称 CRG 架构):
- RZone(Region Zone):直译可能有点反而不好理解。实际上就是所有可以分库分表的业务系统整体部署的最小单元。每个 RZone 连上数据库就可以撑起一片天空,把业务跑的溜溜的。
- GZone(Global Zone):全局单元,意味着全局只有一份。部署了不可拆分的数据和服务,比如系统配置等。
实际情况下,GZone 异地也会部署,不过仅是用于灾备,同一时刻,只有一地 GZone 进行全局服务。GZone 一般被 RZone 依赖,提供的大部分是读取服务。
- CZone(City Zone):顾名思义,这是以城市为单位部署的单元。同样部署了不可拆分的数据和服务,比如用户账号服务,客户信息服务等。理论上 CZone 会被 RZone 以比访问 GZone 高很多的频率进行访问。
CZone 是基于特定的 GZone 场景进行优化的一种单元,它把 GZone 中有些有着”写读时间差现象”的数据和服务进行了的单独部署,这样 RZone 只需要访问本地的 CZone 即可,而不是访问异地的 GZone。
“写读时间差现象”是蚂蚁架构师们根据实践统计总结的,他们发现大部分情况下,一个数据被写入后,都会过足够长的时间后才会被访问。
生活中这种例子很常见,我们办完银行卡后可能很久才会存第一笔钱;我们创建微博账号后,可能想半天才会发微博;我们下载创建淘宝账号后,可能得浏览好几分钟才会下单买东西。
当然了这些例子中的时间差远远超过了系统同步时间。一般来说异地的延时在 100ms 以内,所以只要满足某地 CZone 写入数据后 100ms 以后才用这个数据,这样的数据和服务就适合放到 CZone 中。
相信大家看到这都会问:为啥分这三种单元?其实其背后对应的是不同性质的数据,而服务不过是对数据的操作集。
下面我们来根据数据性质的不同来解释支付宝的 CRG 架构。当下几乎所有互联网公司的分库分表规则都是根据用户 ID 来制定的。
而围绕用户来看整个系统的数据可以分为以下两类:
用户流水型数据:典型的有用户的订单、用户发的评论、用户的行为记录等。
这些数据都是用户行为产生的流水型数据,具备天然的用户隔离性,比如 A 用户的 App 上绝对看不到 B 用户的订单列表。所以此类数据非常适合分库分表后独立部署服务。
用户间共享型数据:这种类型的数据又分两类。一类共享型数据是像账号、个人博客等可能会被所有用户请求访问的用户数据。
比如 A 向 B 转账,A 给 B 发消息,这时候需要确认 B 账号是否存在;又比如 A 想看 B 的个人博客之类的。
另外一类是用户无关型数据,像商品、系统配置(汇率、优惠政策)、财务统计等这些非用户纬度的数据,很难说跟具体的某一类用户挂钩,可能涉及到所有用户。
比如商品,假设按商品所在地来存放商品数据(这需要双维度分库分表),那么上海的用户仍然需要访问杭州的商品。
这就又构成跨地跨 Zone 访问了,还是达不到单元化的理想状态,而且双维度分库分表会给整个 LDC 运维带来复杂度提升。
注:网上和支付宝内部有另外一些分法,比如流水型和状态性,有时候还会分为三类:流水型、状态型和配置型。
个人觉得这些分法虽然尝试去更高层次的抽象数据分类,但实际上边界很模糊,适得其反。
直观的类比,我们可以很轻易的将上述两类数据对应的服务划分为 RZone 和 GZone,RZone 包含的就是分库分表后负责固定客户群体的服务,GZone 则包含了用户间共享的公共数据对应的服务。
到这里为止,一切都很完美,这也是主流的单元化话题了。对比支付宝的 CRG 架构,我们一眼就发现少了 C(City Zone),CZone 确实是蚂蚁在单元化实践领域的一个创新点。
再来分析下 GZone,GZone 之所以只能单地部署,是因为其数据要求被所有用户共享,无法分库分表,而多地部署会带来由异地延时引起的不一致。
比如实时风控系统,如果多地部署,某个 RZone 直接读取本地的话,很容易读取到旧的风控状态,这是很危险的。
这时蚂蚁架构师们问了自己一个问题——难道所有数据受不了延时么?这个问题像是打开了新世界的大门,通过对 RZone 已有业务的分析,架构师们发现 80% 甚至更高的场景下,数据更新后都不要求立马被读取到。
也就是上文提到的”写读时间差现象”,那么这就好办了,对于这类数据,我们允许每个地区的 RZone 服务直接访问本地,为了给这些 RZone 提供这些数据的本地访问能力,蚂蚁架构师设计出了 CZone。
在 CZone 的场景下,写请求一般从 GZone 写入公共数据所在库,然后同步到整个 OB 集群,然后由 CZone 提供读取服务。比如支付宝的会员服务就是如此。
即便架构师们设计了完美的 CRG,但即便在蚂蚁的实际应用中,各个系统仍然存在不合理的 CRG 分类,尤其是 CG 不分的现象很常见。
支付宝单元化的异地多活和灾备
2. 支付宝系统架构图例
典型处理默认
资金处理平台
财务会计
支付清算
核算中心
交易
柔性事务
支付宝的开源分布式消息中间件–Metamorphosis(MetaQ)
Metamorphosis (MetaQ) 是一个高性能、高可用、可扩展的分布式消息中间件,类似于LinkedIn的Kafka,具有消息存储顺序写、吞吐量大和支持本地和XA事务等特性,适用 于大吞吐量、顺序消息、广播和日志数据传输等场景,在淘宝和支付宝有着广泛的应用,现已开源。
Metamorphosis是淘宝开源的一个Java消息中间件。关于消息中间件,你应该听说过JMS规范,以及一些开源实现,如ActiveMQ和HornetQ等。Metamorphosis也是其中之一。
Metamorphosis 的起源是我从对linkedin的开源MQ–现在转移到apache的kafka的学习开始的,这是一个设计很独特的MQ系统,它采用pull机制,而 不是一般MQ的push模型,它大量利用了zookeeper做服务发现和offset存储,它的设计理念我非常欣赏并赞同,强烈建议你阅读一下它的设计 文档,总体上说metamorphosis的设计跟它是完全一致的。但是为什么还需要meta呢?
简单概括下我重新写出meta的原因:
1.Kafka是scala写,我对scala不熟悉,并且kafka整个社区的发展太缓慢了。
2.有一些功能是kakfa没有实现,但是我们却需要:事务、多种offset存储、高可用方案(HA)等
3.Meta相对于kafka特有的一些功能:
· 文本协议设计,非常透明,支持类似memcached stats的协议来监控broker
- 纯Java实现,从通讯到存储,从client到server都是重新实现。
- 提供事务支持,包括本地事务和XA分布式事务
- 支持HA复制,包括异步复制和同步复制,保证消息的可靠性
- 支持异步发送消息
- 消费消息失败,支持本地恢复
- 多种offset存储支持,数据库、磁盘、zookeeper,可自定义实现支持group commit,提升数据可靠性和吞吐量。
- 支持消息广播模式
- 一系列配套项目:python客户端、twitter storm的spout、tail4j等。
因此meta相比于kafka的提升是巨大的。meta在淘宝和支付宝都得到了广泛应用,现在每天支付宝每天经由meta路由的消息达到120亿,淘宝也有每天也有上亿的消息量。
Meta适合的应用
· 日志传输,高吞吐量的日志传输本来就是kafka的强项;
- 消息广播功能,如广播缓存配置失效;
- 数据的顺序同步功能,如mysql binlog复制;
- 分布式环境下(broker,producer,consumer都为集群)的消息路由,对顺序和可靠性有极高要求的场景;
- 作为一般MQ来使用的其他功能。