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


    注:本文整理自美丽联合集团资深工程师陈宗在 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、以及异步化,持续不断去优化。另外,资金无小事,如何提升支付系统的稳定性也是重点考虑的方向。

  • 相关阅读:
    正经学C#_循环[do while,while,for]:[c#入门经典]
    Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常
    asp.net core 获取当前请求的url
    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be
    用orchard core和asp.net core 3.0 快速搭建博客,解决iis 部署https无法登录后台问题
    System.Data.Entity.Core.EntityCommandExecution The data reader is incompatible with the specified
    初探Java设计模式3:行为型模式(策略,观察者等)
    MySQL教程77-CROSS JOIN 交叉连接
    MySQL教程76-HAVING 过滤分组
    MySQL教程75-使用GROUP BY分组查询
  • 原文地址:https://www.cnblogs.com/davidwang456/p/7550020.html
Copyright © 2020-2023  润新知