一个细节翔实、可供参考的支付体系架构演进实例

百家 作者:InfoQ 2017-08-02 12:11:48
作者|陈宗
编辑|小智
从单一功能到完整体系、从臃肿单体 Php 演变为高性能高可靠可伸缩的分布式服务架构,于 16 年快速融合美丽说和淘世界支付体系,并在历年大促中保持无故障的出色表现,逐渐摸索出适应全集团复杂业务形态和变化的支付平台架构。具体是怎么做的?

注:本文整理自美丽联合集团资深工程师陈宗在 ArchSummit 深圳 2017 上的演讲,原题为:《支付体系架构与实践》。

上篇:支付体系架构演进

在过去 4 年的时间里,作为面向亿级用户的大型时尚消费平台,美联集团历经着高速的业务增长和快速的业务演进。而其中最重要的基础业务平台,美联支付如何稳打稳扎、平滑演进,快速适应并高效支持着业务的复杂变化。我们从单一功能到完整体系、从臃肿单体 Php 演变为高性能高可靠可伸缩的分布式服务架构,于 16 年快速融合美丽说和淘世界支付体系,并在历年大促中保持无故障的出色表现,逐渐摸索出适应全集团复杂业务形态和变化的支付平台架构。

支付系统 1.x

13 年下半年的时候,蘑菇街从导购平台转为电商平台。为了支撑电商业务,我们快速实现了第一代的支付系统。当时蘑菇街的业务简单、玩法单一。如图 1.1 所示,第一代的支付系统只包含了支付最核心功能,从而尽快的支撑业务。在这期间,我们实现了面向业务的收银台、支付模块,面向资金端的账务模块,以及与三方支付对接的渠道网关。

1.x 支付系统架构

随后的几年,美联的业务进入超高速的发展,电商交易、以及支付的业务复杂度剧增,玩法多变。同时,在经历数次大促之后,我们发现,支付核心链路大促 QPS 峰值达到了日常的百倍以上。在这种情况下,我们其实遇到了蛮多的问题,以下分为三部分来说下我们当时碰到的问题:

业务问题

1.x 支付系统构建的时候,支付系统设定了比如担保交易、提现等支付交易表。但是随着业务越来越复杂,我们加了越来越多的支付交易表,整个系统的架构如同图 1.2 所示的烟囱型架构。当时来一个业务,我们加 1-N 张表。

烟囱型系统机构

截止到 15 年底,整个支付系统存在这数十个支付交易表。这么多的表,侧面反映了我们对支付业务并没有做模型的抽象,只是在业务的野蛮生长下,不断的应对和接入。同时,在这种情况下,业务的边界很模糊,经常有业务,一半的业务逻辑实现在业务方,一半的业务逻辑在支付方。

系统问题

当时我们整一个支付系统都在一个巨大无比的单体 php 应用里。虽然系统在演进,也分出了不少的模块,但是大家知道。在一个巨大的单体应用里,比较容易出现各模块的耦合,比如支付模块调用了渠道网关模块的一个内部的方法等等。而另外一个,支付团队的几十号同学每天都在一个应用里面开发 & 发布。任何一个地方跪了,都有可能让支付系统崩溃,稳定性非常低。

最后,电商平台的特性,决定了我们必须要不断的提升支付系统的性能。在 15 年的时候,我们对支付系统的 DB 进行了基于模块的垂直拆分,如下图所示。以用于提升系统容量。但这种情况下,我们还是碰到到性能瓶颈。

举个例子:15 年双十一,当时定下来系统能够支持 2kqps 的峰值支付性能。但在数轮链路压测之后,即时我们对 DB 进行了垂直拆分,并用了最好硬件 fushion IO, 但是我们发现系统仅能支撑大概 1800qps 左右的支付。当时其实是比较绝望的,我清楚的记得在 15 年的 10 月底,11 月初的很多白天黑夜,紧急对支付系统的担保交易下单进行了改造,添加了一系列的缓存,最终性能勉强能够达标。

支付系统 DB 垂直拆分

资金问题

第一代的支付系统中,我们对各个业务方的支付接入,并未提供任何的授权和鉴权。也就是说任何系统、任何团队都有可能调用支付系统接口进行资金操作,当时支付有一个万能的转账接口,业务方接入确实很方便,但其实埋了蛮多坑。虽然当时我们支付的业务做了日志记录,但是在数据库里面,我们并未能区分来源的业务、哪种操作,导致了我们对各项业务的流水、收入、支出难以统计和核算。

另外我们当时也碰到了数据一致性挑战。当时支付系统仅有内外部渠道对账,而对内部的业务数据,并没有做好对账事宜,经常出现用户反馈异常问题,然后我们才能知晓。

支付体系 2.0 架构实践

1.x 的支付系统中,其实我们碰到了很多的问题,痛定思痛,我们决心对支付体系做一次架构升级。那么,怎么去做支付体系的架构升级呢?,我们从两个方面来进行架构升级梳理:

  1. 巨大的单体应用必须得拆分,在拆分之前,我们需要确定业务、系统边界,对支付业务进行建模。

  2. 构建完整的资金核算体系,以达到能够清晰的知晓各类业务的流水、收入、支出等。

拆分系统边界

那么单体应用拆分之前,那么如何确定边界? 从三个维度对边界进行了拆分:

  1. 基于业务,拆分为面向支付业务,面向资金核算体系

  2. 基于场景,例如依据支付流程等

  3. 基于技术实现,比如出于对系统的性能考虑等

我们对支付体系里面的核心系统拆分为:收银台、交易核心、支付核心、网关、账务、会计、清算、合规等。下图是对核心支付链路流程示意:

核心支付链路流程

支付体系 2.0 整体架构

得益于蘑菇街强大的基础平台 & 中间件系统,比如 RPC 服务框架 Tesla,数据库中间件 Raptor,可靠的消息中间件 Corgi,数据库事件变更中间件 Pigeon,数据配置推送平台 metabase,分布式缓存 kvstore 等等。我们在 15 年第四季度,对支付系统做了整体的服务化拆分。大家可以看下图支付体系 2.0 的整体架构图:

支付体系 2.0 整体架构图

如图所示,我们大致介绍下各系统的功能:

  1. 面向支付业务拆分为:收银台、交易核心、支付核心、渠道网关

  2. 面向资金核算拆分为:账务、会计、清算、合规

  3. 其他基础服务,比如支付会员服务,支付风控和支付对账等。

支付体系 2.0 系统拆分

上文中呈现了支付体系 2.0 的整体架构,我们接下来对各核心系统的拆分和实现进行介绍:

交易核心

从刚才的支付链路可以看出,交易核心作为支付系统入口,对接上层的业务系统。在 15 年底,支付系统有着数十张的支付交易表,如何抽取合适业务模型,是我们最重要的事情。另外,为了数据的统一性,我们对分散数十张的支付交易表进行了多表聚合,以及订单关联。同时,支付的接入管控也放在了交易核心实现,整体的架构如下图所示:

交易核心架构图

基础交易类型抽象

交易核心里面如何做基础交易类型的模型抽象?主要还是基于对支付的理解,如图 2.4 所示的例子中,电商交易的预售 和 广告营销的购买,都是从用户购买直接到收款方。那么我们可以抽象为即时交易,即直接从 a 用户到 b 用户的支付行为。

基础交易类型抽象

基于对业务的分析理解,我们对交易核心的业务进行了抽象,抽象为 10 多种交易类型:

  • 大家比较熟悉的:担保交易、即时交易、充值、提现、担保退款、即时退款、转账等。

  • 以及不太常见的:提现退票、退款退单、异常退款、充值退款等。

多表聚合 & 订单关联

我们对数十张的支付交易表进行多表聚合,是基于一张主表来实现。而在这种情况下,业务订单如何保持唯一是我们需要考虑的事情。考虑到需要对上层业务的极少侵入性,在新设计的支付交易表中,有专门的字段用于做唯一键约束:

业务识别码 + 业务订单号 来进行订单唯一约束。

另外,做了一个小功能,任何订单都可以追溯到初始单,如下图为例,担保交易下的所有的单子都可以找到,同时也能追溯到初始的订单。

担保交易订单关联

支付管控

鉴于交易核心为支付平台的入口,针对 1.x 支付系统中支付接入无授权问题,我们也在交易核心里面做了支付接入的管控,授权 & 鉴权。为任何一个接入支付的业务分配唯一的业务标识码 & 授权的 token。从而使得业务在支付接入时,须带上 token & 加盐过的加密数据传入。

支付核心

我们将 1.x 支付系统里面的支付模块,切分两层,交易核心 & 支付核心。交易核心面向上游业务,支付核心面向支付系统内部。

支付核心整体架构如图 2.6,我们对支付核心同样进行了支付类型的抽象:充值、提现、退款、转账四类,任何一个交易核心订单请求,都能被四种基础支付类型组合进而完成支付行为。另外,支付核心需要基于系统、用户指令等完成各种各样的支付行为。按照简单的做法,我们可以在不同的分支上实现各式的支付行为,但是这样可能会导致支付行为的耦合,以及支付的复杂逻辑判断。基于这种原因,我们对支付工具进行组件化拆分,封装为数十种支付工具,通过支付编排来执行支付行为。

支付核心架构图

支付行为编排

支付交易订单通过支付规则生成具体的支付请求(即支付核心记录),支付请求通过支付指令编排规则,获取一组支付工具包。通过支付执行器完成对支付工具的调用执行。这样的封装,我们可以实现插件式开发,以及可支付规则可配置化,继而让支付核心内部的支付工具互不影响 &  系统简化。整个编排过程如下图所示:

支付行为编排

异常处理机制

支付核心有一个比较重要的功能,是如何对支付异常进行处理,支付过程比如重复支付、部分支付、金额不一致、其他异常全额退款等等异常,都需要做异常的退款。

如图 2.8 以部分支付为例,我们做了一个异常管理组件来处理这种异常,在网关支付 + 红包 + 优惠券组合支付中,对每次的支付都进行上报。红包支付、优惠券支付,都成功上报,而对于网关支付异常时,也做异常上报机制。通过异常管理组件对部分支付成功的行为进行反向异常退款。

部分支付异常退款

渠道网关

我们对渠道网关系统进行拆分,渠道网关接受来自支付核心的支付请求,与三方支付进行交互。

网关系统同样抽象了基础服务类型:支付、退款、提现、签约、查询等。同时,为了性能考虑,网关系统切分为两个子系统,网关核心 & 网关前置:

  1. 网关核心负责渠道路由、渠道订单的管理、以及渠道的分组。

  2. 网关前置负责渠道适配、报文转换、以及外部通讯。

整体架构如下图所示

渠道网关整体架构图

资金核算体系

资金核算体系主要由账务系统、会计系统、清算系统 和合规系统组成,整体架构如下图所示:

支付核算体系

  • 账务系统:由支付核心驱动,记录管理账户信息,直接反应用户的账户余额和资金变更明细。

  • 会计系统:对业务运转信息进行管理、核查、披露。 展现资金的来龙去脉。

  • 清算系统:由支付核心驱动,实现机构间资金关系应收应付的主被动清算以及资金划拨。

  • 合规系统:基于支付数据,向资金监管方同步交易信息流 & 资金流,从而契合央行合规监管要求。

截止目前,我们对支付体系的面向业务的系统 & 资金核算体系进行了介绍。

统一平台业务上下文

1.x 支付系统单体应用通过确定系统边界、业务建模拆分之后,整个支付平台被拆分几十个服务,而如何保障在服务间流转业务信息不被丢失,是我们需要考虑的问题。就好比如何让各个系统交互时都讲普通话,而不是讲方言。针对这个问题,我们做了平台统一上下文的要素信息(唯一业务标识码),在整个支付平台链路中全程传递,具体要素如下:

  • 商户:诸如 mgj 交易 & mls 交易等。

  • 订单类型:基于交易核心的业务类型,诸如担保交易、即时交易、转账、提现等

  • 订单场景:诸如电商预售、营销广告购买等

  • 支付机构:诸如支付宝、微信等

通过统一平台业务上下文,我们能够在任何一个系统里面清晰看出是哪种业务,在哪种场景下,使用哪个渠道做了什么事情。

直面数据一致性挑战

在单体应用服务拆分之后,我们碰到了更加严峻的数据一致性挑战,系统间交互异常、无分布式事务的情况下,数据不一致的情况出现的概率还是非常大。

那么我们是如何解决数据一致性问题的?总结下来有三个方面:

CAS

在整个支付平台中,我们对可能有并发冲突的系统做了 CAS 乐观锁 ,以交易核心、支付核心为例,通过状态的 CAS 乐观锁防止并发,如下所示:

update PayOrder set status='complete' where id=1 and status='process'

同时,也做了基于 KVstore 的分布式缓存锁来防止多数据之间的并发问题,例如解决重复支付问题等。

接口幂等 & 异常补偿

我们要求整个支付体系中的所有服务,涉及数据变更的接口都要求保持接口幂等。通过全链路的幂等,使得重试成为了可能。

在诸如服务超时、网络异常的情况下,我们做了两种不同的异常补偿:基于消息中间件 Corgi 的准实时补偿 & 基于异常表的补偿。

以支付回调链路为例,如下图所示,渠道网关和支付核心之间的交互,使用的两者补偿的方式。交易核心 对电商交易的支付成功通知方式,我们使用异常表的补偿,在 12 小时内递衰的通知 10 次等等。

支付回调补偿机制

完整对账体系

在支付体系中,对账是数据一致性的最后一道防护。对账可分为两部分:

  1. 内外对账,是 1.x 支付系统上线之后已经实现该功能。确保美丽联合集团支付数据与三方支付的数据保持一致。

  2. 内部业务对账,在 2.0 支付体系构建过程中,我们做了一套内部业务准实时对账系统,用于核对整个平台数据。

下面对内部准实时做简单的介绍:

内部准实时对账

如下图所示,准实时对账平台支持各种数据源的接入,目前基于系统解耦的考虑,我们更多的使用数据库事件变更中间件 Pigeon 来接入对账双方的 binlog 数据,通过配置的规则 或者自定义的转换逻辑来进行双方的模型转换,从而通过对账核心进行数据的核对。目前通过该系统,我们可以在 5-25min 之内,发现异常数据。目前支付核心链路全部接入,支付全平台 95% 以上。同时由于对账系统的普适性,目前已经推广至公司所有业务。

准实时对账平台架构图

基于上述的这些手段,我们能够保障支付系统数据的最终一致性。

疗效?

那么通过对支付体系的升级架构,我们取得了哪些成果?

  1. 快速支撑业务。之前在接入新的业务的时候,大概率需要新增交易表以及开发上线。目前在升级之后,我们基本上只需要进行接入配置即可。

  2. 16 年快速融合淘世界、美丽说支付系统。在融合的过程中,新版的支付系统能够兼容当时的淘世界 & 美丽说支付系统,顺利的完成了融合。

  3. 基于业务接入授权管控 以及平台统一上下文,我们能够对业务进行细分,从而能够对各业务的资金情况进行细分和准确的核实。

  4. 通过合规系统的实现,符合央行的资金监管要求,为用户、商户提供了强有力的资金安全保障。

总结展望

通过对业务的梳理、系统边界的拆分、业务建模等手段,我们完成了对支付体系 2.0 架构升级,进而能够对业务提供更加高效、稳定、专业的支撑。进一步的提升了资金的核算 & 管控能力。但是目前的支付平台里,每个子系统中,或多或少的都存在着自己的配置系统,虽然是基于公用的统一的平台业务上下文,但是配置还是繁琐。如何做到统一化配置也是我们后续考虑的重点。同时,目前平台业务统一上下文的四要素是基于交易核心出发,从目前的系统演化来看,我们需要继续改进为更优化的模型,以应对后续更加复杂的各类业务。

下篇:容量提升

在对美联支付系统升级到支付体系 2.0 之后(支付体系架构演进)。那么我们针对电商平台特性,比如大促时支付链路峰值为日常的百倍以上等等特性,又做了哪些性能和稳定的提升?

下面我们以支付核心链路为例,谈谈如何提升支付平台的性能和稳定性。

支付核心链路

性能提升

针对于电商特性,我们对支付平台的性能提升主要是从以下几个方面优化:

  • 核心链路分库分表:全链路水平扩展

  • 服务调用异步化

  • 热点账户问题优化

  • 事务切分

核心链路分库分表:全链路水平扩展

目前所有的应用服务都是无状态,理论上应用服务可以做到无限扩展,目前最大的瓶颈是在 DB。性能容量的提升,关键在于 DB 的容量。基于这个原因,我们对整个平台的 DB 做了水平的拆分。

在全平台水平扩展的过程中,我们以核心链路为例,从交易核心、支付核心、账务核心、渠道网关等系统全部做了数据库的水平拆分。基于交易核心、支付核心、渠道网关等系统,前面介绍过,我们抽象了各种基础模型,数据都是基于一张主表存储,因此水平拆分基于该主表即可。

得益于美联自研的数据库中间件 Raptor,我们实现链路的分库分表。同时,也基于全局统一的 sequence 生成器,保持了所有分片内的主键 id 唯一性。

支付核心链路分库分表

服务调用异步化

支付体系 2.0 升级之后,单体应用拆分为数十个服务。系统的拆分和服务化,其实带来了更多的系统依赖。相对于之前的单体应用,从方法级的调用方式变更为 RPC 服务调用,网络耗时 & 同时网络的稳定性等因素也是需要考虑的问题。基于这些考虑,非强实时的服务调用,异步化是最佳的解耦方式。同样,在核心链路里,我们也做了各种各样的异步化优化,进而提升整体的链路性能,满足电商平台独有的性能特性要求。

我们从几个点来看下如何对支付系统做异步处理:

支付消息报

基于数据库事件中间件 Pigeon & 消息队列 Corgi,我们实现支付消息报。如图 1.2 所示,支付消息报基于交易核心数据,聚合支付核心的支付数据,最终生成支付消息报。通过这种方式,将原本需要在交易核心或者支付核心调用下游业务方,或者下游业务方实时查询的方式,转变为下游业务方通过接受消息的推送来获取数据,从而达到了业务的解耦。同时,也简化了业务方的数据获取复杂度。

支付消息报架构图

目前支付消息报已经接入了 10 多个业务场景,例如满返,支付成功短信通知,风控所需的支付数据等等,并在持续不断的增加中。

外部支付异步化

在外部支付中,经常会碰到这种情况,需要服务方与第三方支付交互,获取预支付凭证,如图 1.3 所示。这种同步调用的情况下,由于需要跨外部网络,响应的 RT 会非常长,可能会出现跨秒的情况。由于是同步调用,会阻塞整个支付链路。一旦 RT 很长且 QPS 比较大的情况下,服务会整体 hold 住,甚至会出现拒绝服务的情况。

同步调用三方支付

基于这个问题,我们对这种获取预支付凭证的方式进行了改进,详见下图:

异步调用三方支付

通过独立网关渠道前置服务,将获取的方式分为两个步骤:

  1. 针对支付链路,只是请求到渠道前置拿到内部的支付凭证就结束了。

  2. 针对外部请求,由渠道前置异步向三方支付发起请求。

那么基于这种方式,与三方支付的同步交互仅仅会阻塞渠道前置。密集型的 io & 低 cpu 系统,渠道前置的并发值可以设置的非常大。

异步并行

支付平台服务化之后,核心链路上的服务多为 IO 密集型,这里我们以收银台渲染为例,见下图。

串行模式下的收银台渲染

一次收银台渲染,串行的调用各个服务来进行用户信息查询 (RT T1)、额度查询 (RT T2)、优惠查询 (RT T3),最终执行渠道渲染 (RT T4),这种实现方式下

收银台的渲染 RT = sum(T1,T2,T3,T4)

但是收银台的渲染 RT 必须要这么久吗?其实对于业务的分析,我们发现其实很多的服务调用无先后顺序。用户信息查询、额度查询、优惠查询这三个服务的调用其实无先后顺序,那么我们基于 Tesla 服务框架的异步化服务调用,见下图。

异步并行模式下的收银台渲染

基于异步并行的收银台渲染方式,将并行过程中的各服务化的耗时之和变更为耗时最长的一个服务的 RT。

收银台渲染 RT =sum(max(T1,T2,T3),T4)

资金核算体系异步化

目前支付平台里,资金核算体系各个子系统:会计系统数据来源于账务系统,账务 、清算 、合规数据来源于支付核心。那么,需要在支付核心链路执行的时候同步调用账务 & 清算 & 合规,账务实时调用会计吗?其实基于对资金业务的分析,会计、清算、合规属于非强实时业务,可以通过数据变更中间件 Pigeon 同步数据,对这三个系统进行了解耦,如图:

资金核算体系异步化架构

清算、合规通过监听支付核心 DB 数据变更来获取数据,会计通过监听账务的流水库的数据变更来获取数据,从而对实时链路非强实时业务进行解耦。

热点账户问题优化

热点账户应该是每一个做支付的童鞋都会碰到的问题。美联的支付系统里,存在这各种各样的热点账户,我们将之分为三类:

  1. 内部户:比如渠道的待清分账号等

  2. 平台户:比如各种平台的营销的垫支户等

  3. 大商家的热点账户等。

每种热点账户的业务属性都不一样,比如商家账户,我们不能延迟记账等等。基于这些情况,我们对热点账户问题优化也基于类型:

内部户

针对于内部户,我们在账务中不做内部户这边的记账,而是由会计通过另外一边的账务流水去补分录。

平台户

针对于平台户,在账务中做了异步记账,通过定时汇总记账即可。

大商家

比较难的是大商家的热点问题,特别是在美联这种没有商家结算周期的情况下,每一笔的订单状态变更,都有可能涉及商家的账户资金变更。但是也有解决办法。分析其业务场景,担保入账、担保出账 、佣金扣费等占用了绝大多数的商家账户操作。针对这块我们分为两个点来做优化:

  1. 将商家担保账户切换到平台担保户,基于流水去统计商家担保中的金额。这种情况下,担保入账和出账的商家热点问题可以解决。

  2. 第一点的优化能够解决担保出入账的账务操作,但是扣费依旧会造成大量的热点账户问题,对此我们做了一个排序的任务,将扣费做到做到单商家串行 & 多商家并行。

基于上述的两个优化方案,我们解决了大商家热点账户问题。

通过对三种类型的热点账户优化进行,能够解决目前系统碰到的热点账户问题。但是各种平台户的账务流水会非常多,以担保户为例,每日的所有的出入担保户的流水,都会在这个账户之上,那么在分库分表情况下,会出现平台户所在的单表巨大无比。在这里我们引入二级子账户概念,将内部户 & 平台户在账务虚化成 N 个二级子账户,从而均匀的分散在各个分表里,进而解决了该问题。

账务记账事务切分

在支付核心链路里,我们对非强实时依赖的服务做了异步化的解耦,对热点账户进行了优化的处理。在账务记账的时候,我们从下面两个问题考虑优化点:

  1. 在账务分库分表的情况下,如何保证记账是在事务里?

  2. 每次记账的出账 & 入账是否可拆分?

基于这两个问题,我们对记账流程进行了事务的拆分,如图所示:

账务记账事务拆分

  1. 出账、入账分离。出账成功,则整体成功,入账失败可以异步补账。

  2. 出账 & 入账 ,每个里面都做单边账、异步记账等处理,整个支付核心链路唯一的一个事务就在于更新账务余额  & 新增流水。

目前系统中,经过这一系列的优化,单次的记账性能,基本上稳定在 15ms 左右。

稳定性提升

在上文中,我们主要针对于支付链路的性能做了各种各样的性能提升。资金无小事,如何保证支付平台的稳定性,也是我们需要考虑的重点。我们从下面几个维度来提升稳定性。

监控先行

做稳定性之前,我们需要知道我们的系统运行情况,那么必须要做线上系统的监控,对关键指标进行管控,以支付核心链路为例,如图:

核心链路监控

如图所示,我们监控了核心链路的 qps、rt、并发量等,同时也基于支付核心,我们对依赖的服务 qps、rt 进行监控。另外,也对依赖的 DB & Cache 进行监控。

通过在监控大盘中配置关键指标,能够比较清晰明了的看出目前核心链路线上运行情况。

分离核心链路

基于电商特性,我们对整个核心链路进行了剥离,如图所示:

分离核心链路

对核心链路分离的过程中,我们对链路中的各个服务中切分为核心 & 通用服务。分离的做法其实有很多,比如基于 Tesla 服务框架提供的服务分组功能;比如将一个服务切分为两个服务:核心链路服务和通用查询服务。

在核心链路分离之后,能够确保在任何时候,核心链路不会受到其他通用业务的影响而导致出现稳定性问题。

服务依赖梳理

目前在支付系统里,有着数十个服务,如果不对服务依赖进行梳理,系统稳定性会得不到保障。我们从下面几点来梳理服务依赖:

  1. 梳理平台中的强弱依赖,判定哪些是强依赖,哪些是弱依赖。

  2. 弱依赖做好降级和超时保护,比如收银台渲染是的白付美额度查询,这种可以埋降级开关 & 设置较短的超时时间。因为查不到额度,最多不能使用白付美支付,并不会有特别大的影响。

  3. 如果是强依赖,这个不能降级,怎么办?需要对强依赖的服务提出服务的 SLA 治理,比如账务记账功能,我们会要求系统不能挂、rt 不能超过 20ms,qps 需要支撑 8k qps 等等,基于这个约定,做子服务的优化。

降级、限流

限流是保护系统不挂的最后一道防线。

目前支付平台里面,存在基于 RPC 服务框架 tesla 的粗粒度限流,可控制在服务级别和方法级别;基于 spirit 的细粒度限流降级系统,我们可以在单个方法里面做限流降级功能个,如下图所示,我们在担保交易下单过程中,区分平台来源,做到蘑菇街担保交易流量 & 美丽说担保交易流量。

spirit 限流模式

但是不得不说,单单的 qps 或者并发限流都不能完全的做好限流保护,需要两者的相结合才能达到所需的效果。

另外一点,通过对服务的依赖梳理,我们在各种弱依赖的服务中埋了一些降级开关。通过自研的降级推送平台,一旦依赖服务出现问题或者不可用,可以快速的对该服务进行降级操作。

压测怎么做?

在对系统扩容,链路性能优化之后,怎么检测成果呢?

  1. 我们引入线上压测系统,通过分析业务场景,构建与线上真实场景几乎一致的测试模型。以支付链路为例,模型中以日常 & 大促的流量模型为基准,设计压测模型。需要注意的是,压测模型越与真实一致,压测的效果越好,对系统把控越准确。。

  2. 通过构建线上数据影子库,压测产生的测试数据,会全量写入到影子库中。通过影子库,在复用线上正式业务一致的环境、部署、机器资源下,我们能够做到压测对正常业务无侵入,对系统做准确的把脉。

  3. 线上业务也分为两块,一块是单机性能压测,主要是分析单机的性能水位和各项指标。另外是链路压测,主要验证系统的稳定性和服务短板。

通过压测的结果,我们能够对支付平台的性能 & 稳定性短板的分析和加以改进,能够不断的提升系统的稳定性,提升系统的容量。

疗效?

那么,通过一系列的性能容量的提升,我们达到了什么效果?

  1. 平台容量方面:在 16 年双十一的大促压测中,我们在链路 DB 都扩围两组的物理的机器情况下,支付稳定在 3000QPS。由于目前没有需求,我们未对 DB 的物理机器扩到极限,因此系统的极限性能不能完全确定,但是按照预估,理论上可支持 1w QPS 以上。

  2. 机器利用率上:相同的容量情况下,我们的应用减少为原有的 1/3。

链路的性能上:如图 4.1 所示,以担保交易为例,交易核心的收单 rt 几乎在 10ms,而收银台渲染在 50ms,支付请求在 50ms,支付回调在 80ms 左右。

核心链路服务性能

同时,基于性能和稳定性的提升,我们做到了支付在历次的大促中,保持无故障的记录。

总结展望

在美联支付系统中,上层支付业务面向电商平台,针对电商特色做更多的业务支持。我们对平台的性能容量寻找可改进的地方,比如 DB、Cache、IO、以及异步化,持续不断去优化。另外,资金无小事,如何提升支付系统的稳定性也是重点考虑的方向。

作者介绍

陈宗,花名铁手,14 年加入蘑菇街。参与美联支付技术历次重大优化与演进,主导支付体系中交易和支付系统的平台化架构,并持续钻研和改进具有电商特色的支付平台。目前在支付团队负责支付基础平台架构和研发工作。


互联网讲求唯快不破,飞速的业务发展对服务架构提出更高的要求,业务需要强大的服务架构来支持更加复杂、量级更大的业务。QCon 上海 2017 全新开启,更多企业架构实践案例,敬请关注。

QCon 上海站目前 8 折优惠报名中,2017 年 08 月 20 日前,立减 1360 元,团购报名更多优惠~点击【阅读原文】跟技术大咖零距离。欲购票或咨询问题可联系购票经理 Hanna ,电话/微信:15110019061。


今日荐文

点击下方图片即可阅读

如何面试工程师?


关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接