20171230-支付系统曾经遇到的坑和解决方案

Posted by PaymentGroup on December 31, 2017

一、主题分享

今天给大家分享一下支付方面遇到过的问题,主要是这4个方面遇到的问题:

  1. 流程混乱和沟通问题导致事故
  2. 初期经验不足导致事故
  3. 依赖服务和外部原因
  4. 监控系统功能不全和报警及时

1.1 流程混乱和沟通问题导致事故

  1. 开发人员编写的sql语句让DBA执行,DBA没有经过严格的审核sql的执行目的和正确性,拿着sql语句直接执行导致事故。遇到二种:其一,是从oracle中导出数据让dba执行sql插入数据到生产库,导出sql是先删除表在创建表插入数据,本来目的是新增数据结果把以前的数据删除了;其二,修改订单是sql写的不正确,没有经过严格审核导致事故。
  2. 运维人员没有经过开发同学的确认,自己私下练习调灰度环境,导致生产的mq消息被抢走,引发交易事故。
  3. 实操人员和用户确认好的异常交易需要手工修改单,转手运营人员给单号让开发人员修改订单状态,运营人员把单号复制错误,技术人员没有审核直接修改导致修改订单错误。
  4. 新来的测试人员,还不熟悉流程,接到任务压力测试批量代付功能,没有沟通的清楚的情况下随便挑了测试数据信息,批量压测导致真实交易发生导致交易事故(金额巨大)。

1.2初期经验不足导致事故

  1. 开发同事在新接入三方支付渠道时,由于经验不足忽视了设置超时时间的重要性,导致这个三方队列所在的交易全部堵塞,同时影响到其他三方支付渠道的交易(队列未拆分)。
  2. 系统是分布式部署使用同一个库,并且支持灰度发布,环境和部署模块非常多而且复杂。某次增加了一个新模块,由于存在多个环境,且每个环境都是双节点,新模块上线后导致数据库的连接数不够用,从而影响其他模块功能。
  3. 同样是超时问题,一个三方的超时,导致耗尽了当前所配置的所有worker threads,以至于其他交易没有可处理的线程。
  4. 数据库序列问题,oracle数据库建立的不是循环序列,当序列使用完后无法创建序列导致交易事故。
  5. 参数校验问题,必传的参数服务端没有做好校验(默认为业务一定会传),业务线接口问题没有传必要参数,使用mybatis导致数据库全表扫描,更严重的是开发人员还把查询结果打印一个tojson的log导致内存溢出。
  6. 并发数没有控制好,三方支付渠道的并发限制没有控制,导致交易大时出现大量的交易失败,部分三方支付渠道是对商户的并发有要求的。三方支付渠道给开放几个并发是根据实际交易量来评估的,所以如果不控制并发,大量的交易都发给三方支付渠道,那么三方支付渠道只会回复“请降低提交频率”之类的信息。
  7. mq队列拆分不够细,如多个三方渠道共用一个队列,其中一个三方渠道发生异常,会影响其他三方渠道。
  8. 前置网关使用hibernate,由于开发人员对hibernate的自动更新把控不好导致交易状态异常(影响比较大)。

1.3依赖服务和外部原因

  1. 短信平台单点的问题: 由于有鉴权和快捷支付(以及包装的快捷支付),由于大部分的交易快捷是自己平台发短信,当短信平台出问题时,所有依赖短信的交易全部瘫痪。
  2. Mq服务单点的问题,遇到某天mq服务器坏掉了所以交易瘫痪。
  3. 接入渠道单一,当某渠道维护和不出问题整个业务无法进行。
  4. 支付公司维护和不稳定时解决方案。

1.4 监控系统功能不全和报警及时

  1. 三方渠道不稳定不能及时发现。
  2. XX渠道的失败率过高不能及时发现调整。
  3. 系统内部错误不能及时发现,如批量代扣由于其中一笔交易数据问题,影响整个批次的发送处于中间状态,需要立即报警发现。

1.5 解决方案

这里简单描述下应对上述问题的方案:

  1. 规范流程增加多人审核尤其是代付交易和sql;
  2. 每个业务线接入的通道不能单一必须二个以上,当一个出现问题或不稳定,路由调整到稳定通道上;
  3. 队列尽可以拆分细不同通道一个队列,交易和查询队列分开,不然一个通道有问题导致其他通道不能用;
  4. 交易监控这块尽量实时性比较高;

业务监控点都是在日常运行过程中根据自身业务一点一滴总结出来的,分为出警类和关注类两大块。

出警类:

  • 网络异常预警;
  • 单笔订单超时未完成预警;
  • 实时交易成功率预警;
  • 异常状态预警;
  • 未回盘预警;
  • 失败通知预警;
  • 异常失败预警;
  • 响应码频发预警;
  • 核对不一致预警;
  • 特殊状态预警;

关注类:

  • 交易量异常预警;
  • 交易额超过xxxW预警;
  • 短信回填超时预警;
  • 非法IP预警;

二、 Q&A

Q:调整是人工还是系统自动呢? A:自动调整


Q:架构复杂。流程复杂。数据没有直接落地

A:数据前置系统通过后接落地的,每个服务之间通过状态来控制


Q:什么叫查询队列?这个好奇怪

A:如批量交易,需要做查询,我们会把查询的批次号从查询服务发到通道模块去拼数据发送三方查询,二个服务之间的通信队列就叫查询队列可能名字叫的不是很好。查询服务只是定时回去查询服务条件数据的批次,发送到通道模块去拼数据发送三方查回结果

Q:异步确认吗?

A:异步的,主动查询

Q:批量代扣失败怎么不把出错的。代扣数据存放到另一张表。然后继续执行后面的,并发出告警,毕竟人工干预没那么即时

A:继续执行我们有,是根据是否客户原因重发的,如果是客户原因失败重新发送还是会失败

Q:不是哈。我是说挑出来。让主流程继续跑。有异常的。等人工确认

A:我们是只要不是客户原因就立即发送的,还没有你这种方案,哈哈,你这种方案比较清晰点


Q:你现在有分库分表不?现在是复试记账吗?

A:目前没有,我们是吧2个月的数据迁移到历史表中去,真实库就2个月的数据,单边记账,想搞复试记账,还不会等哪天想听听这方面的大佬分享

Q:现在是记单边帐吗?

A:是的,最近在开始搞对账方面的事


Q:针对第三方支付交易关闭后如何退款的?例如支付宝三个月后为交易关闭不能退款,业务上有押金,这里指原路退回

A1:我们不是电商没有遇到这种需要哈哈,我们的交易一般当天基本上全回来终态,极少第二天回来终态,如果有重复支付这种可以调用三方原路退回接口。

A2:第三方支付关闭不能原路退还的,我们走转账


Q:监控这块大概是如如何设计的呢?mq异步的么?

A1: redis埋点

A2:监控这块我们主要是通过redis埋点收集数据,实时统计分析,以及一些订单交易状态统计同直接查库,不同维度来保证问题及时暴露出来

Q:嗯,统计分析这块用的什么数据库呢

A:目前用的MySQL

Q:分享一下用了哪些开源技术栈呢?

A:没有什么特别的,我们现在都是spring cloud体系这套东西

本文档来自“支付产品架构交流群” 的聊天记录整理,由志愿者整理并发布到本网站。如需要及时收到来自“支付产品架构交流群”的最新消息,请扫码关注“凤凰牌老熊”的微信公众号。目前支付产品架构群还有不少空位。 本群面向支付行业的有经验(2年以上)的产品经理、软件工程师、架构师等,提供交流平台。如想加入本群,请在本文评论中留言(不公开),说明所在的公司、负责的工作、入群分享的主题和时间。