支付网关 | 京东618、双11用户支付的核心承载系统(上篇)

二零一七年六月二十一日,就是年中大促刚结束的那一天,我午饭时间独在办公室里徘徊,遇见X君,前来问我道,“可曾为这次大促写了一点什么没有?”我说“没有”。他就正告我,“还是写一点罢;小伙伴们很想了解支撑起这么大的用户支付流量所采用的技术。”

「摘要」由于设计时我跟小伙伴们把系统的定位更偏向于具有用户支付事务处理能力的消息总线。业务深度耦合涉及比较广,感觉一次性到位说清楚不太可能。故本篇分为上下两篇,上篇仅对支付网关架构和支付业务流程进行基本介绍,采用的全时在线技术里的基础部分说明也放在上篇,下篇则着重介绍全时在线技术的具体化应用以及下级系统重构和迁移过程中的备份切量逻辑。更详尽或代码层级的文章将后续单独推出。

  • 上  篇
    支付网关架构和支付业务流程基本简介
    UUID并发序列生成器
    平行迁移
    本地化存储
    缓存双备
  • 下  篇
    自行收单、
    补单
    异步交互
    路由分流功能

    支付结算平台的交互细节

支付网关作为支付目前的总入口,在最近一次618大促的实战检验中:

承载的峰值用户支付流量TPS为2.2万以上
  承载了期间用户支付的全部流量

经过持续的优化,整个京东支付在用户层就具备了完整的自我闭环能力,完全解决业内普遍存在依赖单支付清算机构的瓶颈问题。在日常和大促期间我们的系统定位主要集中在3个方面:
一、提供高效稳定的扣款支付能力
二、保障友好化的商城客户支付体验
三、高并发场景下的全时在线服务:
    a)        业务模块降级
    b)        基础工具模块热插拔
    c)        流量分布式平行转移
本次618预先启用了分流和缓冲机制,在保证支付体验的情况下,尽可能的预防了核心业务系统、各支付机构被流量冲击打垮的情况。

支付网关架构和支付业务流程基本简介

1、支付网关的架构模块体系:

按照功能主要分为:业务模块、支付渠道模块、体验保障与高速化模块、基础工具模块。大体的纵向各个功能模块的组织谱系关系如下:

2、支付渠道(以下称为:渠道)主要为支付网关(以下称为:网关)提供了支付工具的扣款能力,网关综合各渠道的扣款能力屏蔽机构间的差异,生成核心支付组件。再结合核心的业务控制能力(风控、路由、商品订单)进行流程化封装生成对支付接口。收银台增添一些先决认证条件:生物识别,手机认证(短信、尾号)、SSO登录、设备认证通过后调用网关的支付接口进行支付。

3、详细的业务交互时序流程,以其中一个支付流程为例,大体时序为:

根据业务时序图,做过大型企业ERP、BOSS系统的人看来并不复杂。但在互联网最大的挑战就是大并发的情况。
4、网关的技术架构思想为:
1. 保障核心业务逻辑稳定或无损平行转移,极端情况的下的failback
2. 拆解非核心业务逻辑到异步分支流程.
3. 非核心业务逻辑性能差或故障时降级,并实现failover
4.   取消数据库依赖
5.   基础工具组件双备甚至多备下的热插拔

UUID并发序列生成器

UUID是于2016年2月完全自主研发的业务单号生成系统,对代码进行了开源,完全遵循LGPL协议。支付单号生成是我们收单最重要的一步,由支付单号来流转整个支付流程。

它理论基础是按照能有效组织资源的最细粒度拆分服务单元,根据服务单元的属性差异进行唯一化。唯一化的服务单元互相隔离,由于具有唯一性各节点构成分布式,服务单元内部再按照能有效组织的最细粒度资源进行功能克隆拆分子服务单元,共享资源需要被其中一个子服务单元使用是进行排它独占。

实际解决的问题:生产单号多采用数据库、随机数生成,在请求量较少时问题不显著。随着请求量的加大出现重复、卡死的概率逐渐增加且部署数据库、运营成本较高。很多公司的数据库也不光给uuid使用,在海量事务处理时是常出现仅为生成id就耗费CPU时间片,造成正常业务处理延时。

具体技术实现:
我总共写过三种实现:netty、tomcat做中间件各一版、linuxC一版。我们目前生产环境中使用tomcat版本:

1、注册中心的实现:因为只起到分配实例号的作用。正常情况下tomcat实例终身也只在第一次启动时获取一次实例号。由于压力不在生成实例号,简单实现的话使用数据库单表,表的自增主键作为实例号,表中的md5值为唯一键。自己也可以生成一个注册中心,只需要注意号记录md5和实例号所在文件的文件锁问题即可。生产环境当中我们使用的是mysql.
2、三种生成id的细节性问题:
第一种方式是性能最高最可靠的方式。但由于加入了时间维度,如果在极短的时间内重启完毕,存在单位时间里内存递增变量归0递增后重复的概率,于是加入了延时等待的功能让单个实例启动后延时一段时间再提供id。延时的时间>=时间的维度步长。如:时间维度为1s则实例启动后至少应该延时1s在提供生成服务。
第二方式:适合id号必须连续的场景,比如会计凭证号.但是第二种方式由于没有操作系统文件文件锁的保护,只能当单台机器上只有一个tomcat实例的情况下使用。
第三种方式:适合id号必须连续的场景,比如会计凭证号。由于有操作系统文件锁保护适合单个机器上存在多个tomcat实例的情况使用。
注意:第二、三种方式linux系统对同时打开的文件句柄有数量限制,由于序列名跟文件名一一对应,存在文件句柄资源池管理的机制控制文件句柄能最大效率的使用和按需关闭。

3、有一些公司往往在一台机器上部署多个tomcat实例,所以向注册中心注册时使用的是$catalina.base 而不是$catalina.home.  由于我们用的是docer和jvm虚拟机,一台虚拟机上只能部署一个tomcat不用顾虑这个问题。当然程序进行通用性兼容可以让PE们部署的时候放心用。当然这也就为什么会存在第二种方式获取id方式的原因。

4、Id分单个获取和批量获取,批量获取时采用共享变量直接+批量步长的方式,而不是for循环。减小cpu时间片占用和减少锁长时间占用导致类似starvation现象的发生.

5、存在堆gc对生成id的性能影响,虽然看来非常细微,但是生成id是持久化的第一步。它的每延迟增加1ms往往带来全链路的延时放大。我们后来找到办法,在大促时段消除了gc影响。这个方法我们在后续的技术文章中会专门说明。

平行迁移

平行迁移功能,是我们做故障迁移,流量定位转移的工具。基于UUID生成实例号的原理,所有的实例数量都已经存在了注册中立里,区别在于还要把能标记自己的资源定位符也一起给出来.于是注册中心摇身一变成管理端,起到中介者的角色。以一次业务调用为例:

正常情况下:

当实例1故障时:

1、调用端并不是每次都到管理中心拿映射关系,正常情况下调用端只在第一次系统启动时到管理中心获取对端的URI并记录到本地,只要对端正常就一直会访问。实际我们调用端有个开关工功能控制出现异常时查询还是每次都查询。

2、如果每次都查询管理中心,那管理中心的性能如何保证。目前我们采用纯本地JVM的K-V类型Map + ReentrantReadWriteLock+数据库 进行解决.

3、在第1条中有说过调用端存在开关机制是异常时查询或每次都查询的开关,我们在进行服务端取余结果跟实例对应关系的时候,如果NormalCache赋值的时候以非常小的概率遇到了赋值非原子性操作的问题,无非是两种情况:
一种情况:调用端在利用返回URI访问实例的时候出现异常,这个时候调用端会再去访问管理端查询URI从而避免。
另一种情况:调用端利用返回的URI能正常访问实例,但是我们已经调整映射关系到希望它能访问另外一个实例。其实这个时候场景一般出现在我们密集调整对应关系的时候,这种调整和效果观察的持续时间往往不会短(肯定是秒级以上吧),这个时候我们会打开每次都查询管理中心的开关并持续一段时间,观察访问到了再切回这个开关到异常时查询从而避免。
当然如果你考量这个应用场景还是觉得不放心,那可以在读取的时候用writeLock实现.实际由于全部是内存操作、并且数据库读取在获取Lock之前,这种情况下采用Lock的性能损失接近于无,也非常好。
4、Hash一致性问题,由于这个实例号的生成逻辑是稳定的,由于是实例号是累增不会中间插入,所以目前不存在Hash一致性问题。当然有一些应用场景可能我没遇到,也欢迎大家探讨。

本地化存储

本地存储主要分为两类:
1、一般消息性存储,即把要对外发送的消息出现异常时先存储到本地,然后单独再起线程向原来的接受方进行  传输。由于目前应用场景主要面向消息队列,已经逐渐被我们的部门统一研发的mqSender取代,是对消息队列在客户端的failover机制的一种扩充。如果要是自己实现的话,单就存储而言在采用MappedByteBuffer做内存和刷盘工具+ ReentrantReadWriteLock进行线程隔离就能满足需求,就不多说了。
2、有顺序保障的结构性存储,是我们进行自行收单的基础下篇会详细讲到。如:同一笔支付需要创建支付单(类似财务的应收概念)、写支付结果(类似财务的实收概念)两个动作.业务上要顺序发生并且必须要用数据库进行持久化存储。问题是创建支付单、写支付结果这两个动作实际流程里因为中间涉及用户交互,延时掉单等问题往往存在支付结果先有,而创建支付单延时的情况或者创建支付单的很久以后支付结果才通过别的方式写入(通过银行发异步接口回调,对账单核对)。
首先交易系统层的小伙伴已经把支付结果和支付单放到不同的表内,做insert操作而不是update。其次是如果入库操作出现异常他们首先也会入缓存,等数据库情况变好后再调度入库。等同一笔支付的支付单、支付结果都存在缓存或数据库时再发起下级非实时业务。
而在支付网关的场景是:调用交易系统出现网络失败,写入延时较高的情况下先断掉与交易系统的交互自行发送保存创建支付单和支付结果到缓存和本地。是由于取消了数据库存储,不使用扫描库的方式。而是使用java的io事件selector进行。通过监听SelectionKey.OP_READ事件,根据同一个payid到本地文件和缓存内进行条件判断。判断创建支付单、写支付主任务都成功后再发送消息。

缓存双备双切

在研发体系内有两个自主研发类似redis的缓存系统:JIMDB和R2M,我们同时采用。目的是预防其中中一个出现问题能自动或立即切换到另外一个,采用主从异步模式进行互切:
1、写入时同步写数据到主缓存,异步写数据到从缓存。
2、读取时采用先从主缓存读取,出现异常和超时再在从缓存中读取。如果主缓存使用写入失败,立即调整主从对应的实际缓存。
其实只需要在set和get的时候加一个中间层,与Concurrent框架里的Executor的newCachedThreadPool(ThreadFactory threadFactory)类似,这个结构和实现比较简单:

未完待续

那上篇就到此结束了,下篇将会重点介绍基于这些技术的上层应用功能:
为取消数据库依赖而使用的自行收单、补单功能。
为增加并发量而使用的异步交互功能。
最重要的为预防支付清算机构挂掉而使用的路由分流功能。
为保证下级系统进行重构使用的切量平移功能。
以及为保障历次618,双11活动提前进行的保障和洪峰消解工作。

时间: 2024-10-18 04:38:47

支付网关 | 京东618、双11用户支付的核心承载系统(上篇)的相关文章

四大超能力加持,京东家电双11效率致胜

"价值2万亿的聚会",这句话成了今年双11大战相关话题里最引人注目的内容.10月15日,美的.海尔.TCL.海信.长虹.创维.奥克斯.方太.博世西门子.A.O.史密斯.九阳.苏泊尔.志高等家电制造业巨头的高管和负责人,集体到访京东总部. 这次引人注目的集体会面,被市场人士解读为"电商与品牌间的合作关系进入新阶段".当然,在双11即将来临之际,这场"价值2万亿的聚会"的意义不言而表. 让业界倍感兴趣的是,究竟是什么原因让这些家电巨头们被吸引到这场价

第三方支付网关

在电子商务越来越发达的今天,第三方支付网关也越来越多,虽然第三方支付的公司很多,但在接口方面还是比较相似的,都有一定的规则在其中,比如支付,它势必会有订单生成.支付.返回成功标志.对账等功能,当然,各家网关还有自己独有的一些特点,比如IPS的分账系统. 或许大家会在各家公司之间取舍,就我个人来看,现在做的比较成功的,还算支付宝,有淘宝这个得天独厚的电子商务平台,使支付宝这个第三方成为了国内首屈一指的支付平台,稳定性和安全性都相对比较好.IPS是国内较早起家的第三方支付网关,成熟的商业模式和完善的

[[城市]普及]支付网关,什么是支付网关,第三方支付模式

根据支付网关的建设主体不同,网上支付模式分为1.银行支付网关模式   指客户或商家将支付指令经由银行的支付网关传送到银行后台业务处理系统来完成支付的业务模式2.网上银行模式   是各商业银行完成网上支付的主要业务模式3.共建支付网关模式   由商户收单行或收单行联合发卡组织(如发卡银行)来建立   该模式的支付流程比较复杂   客户在商家网上选商品,填订单   客户端对订单加密并将之发送到商家服务器   商家收到订单后,向网上银行发送订单信息   网上银行在验证商家身份后,向客户浏览器提供支付界

迎双11十周年,OceanBase 2.0挑战新巅峰

2018年是"双11"十周年.2009年11月11日,当时的淘宝商城(天猫的前身)举办了首届网络促销活动,当天销售额为0.5亿元:2017年的双11,天猫.淘宝总成交额1682亿元,创造了25.6万笔/秒的新支付峰值,数据库处理峰值达4200万次/秒.2017双11开始后的7分23秒,支付宝的支付笔数突破1亿笔,相当于5年前双11全天支付总笔数! 对于阿里来说,每年的双11就是一个超级工程,而下一年的双11又会突破前一年的纪录,因此双11其实是一个不停"膨胀"的无限

第八章 交互技术,8.3 2016双11前端突破(作者:天猫前端团队)

8.3 2016双11前端突破 前言 2016 年天猫前端相比去年有了非常多不同维度的突破,主要可以分为四大类大类: 稳定性.监控 极致的性能优化 业务创新 / 平台建设 技术创新 / 互动 1. 稳定性.监控 商品到每个用户浏览的每个环节都有监控,尤其在针对消费者体验上的 TES,让前端在消费者真实浏览的过程当中也能够有更进一步的分析在不同环境下消费者实际的体验.以及从服务器 Wormhole 渲染层进行了一系列的稳定性.监控. 1.1 Wormhole双11会场稳定性保障 Wormhole承

双11同款!阿里云发布全局事务服务GTS:每秒处理10万笔事务

摘要: 5月30日,阿里云宣布全局事务服务产品GTS正式商用,每秒可处理10万笔事务,将分布式事务这个"贵族技术"变为"平民技术 ",可解决跨数据库.消息.服务的分布式环境下的事务一致性问题,让开发者无需考虑复杂的事务问题,加速微服务落地,效率比传统的XA协议提升了10倍之多. 5月30日,阿里云宣布全局事务服务产品GTS正式商用,每秒可处理10万笔事务,将分布式事务这个"贵族技术"变为"平民技术 ",可解决跨数据库.消息.服

中国电信翼支付网关接口接入

最近在做中国电信的翼支付网关接口的接入,正好拿Java练练手.到目前为止,唯一不太适应的就是自己的Java积累几乎为0,什么都要重头写起,不像C#有这么多年的沉淀,可以随手拿来用.   废话先不多说.这个支付接口就和支付宝差不多,无非就是把一些必要的数据参数,POST到指定的接口地址,然后接收它返回的支付结果.接口没有什么复杂的逻辑处理,所以可以直接采用JSP+Servlet+JDBC来做简单处理.对于WEB支付请求的发起,可以从JSP把用户输入或选择的相关数据传到Servlet,然后在Serv

微信支付开发(11) Native支付

关键字:微信公众平台 微信支付 Native原生支付作者:方倍工作室原文:http://www.cnblogs.com/txw1958/p/wxpay-native.html 在这篇微信公众平台开发教程中,我们将介绍如何开发实现微信支付的Native功能. 本文分为以下三个部分: 生成Native支付URL 生成二维码 生成Package 一.生成Native支付URL Native(原生)支付URL是一系列具有weixin://wxpay/bizpayurl?前缀的URL,同时后面紧跟着一系列

Testin云测:从双11看淘宝京东暗战移动电商

Testin云测:从双11看淘宝京东暗战移动电商 2014/11/11 · Testin · 独家评测 一年一度的双11今天凌晨开战,这也是阿里巴巴集团上市后的首个双11,去年单日成交额350亿元的成绩,其中突破1亿元用了55秒,今年3分钟即突破10亿,1小时已突破122亿元."双11"释放惊人的购买力. 值得注意的是,今年双11期间,用户在移动端访问双十一会场的流量几乎达到PC端的两倍,而在往年这一数字只占20%左右,移动时代的双十一终于来了. 多项迹象显示,移动电商已逐渐成为电子商