写在开头,好多人都问我在支付宝是如何处理高并发的。哎~~~~,那我今天就说一下,我是怎么解决每天上百万的还款的,顺便介绍一下高并发的思路。

首先,先看一个图(看不懂没关系,稍后我会解释)。

首先,介绍下,我在支付宝主要负责开发信贷核心系统,它是网商银行的核心系统(不是皮系统),通俗的说就是贷款和还款,当然实际上非常复杂,举个例子,现在国内银行的信贷系统都是从IBM或者oracle买的(开发太难了),而网商这边开发了自己的一套系统。

有一天,有这么一个大需求:资金驱动。我来解释一下,首先,如果用户被打上了逾期或者强制扣款标志,那么,如果你的支付宝账号有money,支付宝受托系统就会给我发消息,然后我处理,最后调用支付宝受托扣款。这是为什么,因为怕用户还不上钱或者不还钱,不然你想想贷出去的钱都收不回来,马爸爸不哭晕在厕所~~~~

言归正传,这个需求看起来特别的清楚明了,但是一般恶心都看起来简单(以往的编程经验)。

看到这个,我于是想到了这个处理办法:

1、接收消息

2、消息落地

3、处理消息,掉支付宝受托接口。

ok,思路清晰,并且完成了。

~~~~~~~~~~~~~~~~~~~~~~~沾沾自喜,当自测的时候,哭晕在厕所,妈的,处理消息的时候简直太慢了,因为对于一个用户,要找出他所有未结清的支用(借据),每笔支用还包含支用账单(分期账单),需要先结息,计算每笔分期账单的表内,表外的正常利息,逾期利息,逾本罚,逾利罚,滞纳金,还有宽限期处理。。。。。(业务极其复杂,学过会计学的就懂了)。造成的问题就是时间太长了,一个事务时间非常长,再加上调支付宝受托接口的时间,太长了。而且网络访问放在了事务中,简直是噩梦(原因很简单:时间太长,事务可能会自动终止,连接不能及时归还导致数据库挂了)。

考虑到以上这个问题,我又想了一个方案:

1、处理消息后将消息落地。

2、起一个调度任务处理消息生成扣款指令。

3、再起一个调度任务负责捞取扣款指令掉支付宝接口。

~~~~~~~~~~~~~~~~~~~~~~~~~so easy,但是当调试的时候发现,我太天真,因为对于每个消息处理很慢(上面介绍过),等我生成扣款指令,消息列表都他妈的都满了,导致消息多的处理不过来,怎么解决?只有优化。

换个思路,既然消息堆积,能不能快速处理消息,当然可以,但是又不能真的去处理消息生成扣款指令,因为太耗时间了,哎~~~~~~

我可不可以这样,在处理消息的时候只是生成相应的记录,也就是生成那个用户要被扣钱了,并不是真的去处理它,然后起一个调度器去处理他。

于是方案变成了:

1、接受消息。

2、消息落地

3、起一个调度器处理消息生成用户扣款记录

4、起一个调度器处理用户扣款记录生成扣款指令

5、起一个调度器处理扣款指令调用支付宝受托

~~~~~~~~~~~~~~~~~~~~~~~~~~~完美!哈哈,终于通过了测试可以上线了。线上运行了一段时间,没有什么问题,好开心。直到有一天的来临,大促!!!!!!!!!!妈的,大促的时候,随着用户的购买,卖家的收钱,账上会不断有资金流入,不停地产生资金驱动消息,而且都是小批量的,数量太大了,上千万条,简直崩溃了。看来还是需要优化!

进一步处理,在观察大促的时候发现,单位时间内,一个商户会不停地有少量资金的不断流入,但是观察发现,其实数据都是一样的,简单都说无非是我收了1块钱,2块钱。只有额度不同,其他的都一样。那么我可以把它们都看成重复记录。哇塞,可以这么处理。我可以去重,然后生成还款指令。

继续优化方案:加油!!!

1、接受消息,并消息落地。

2、处理消息生产前置还款指令(aegis_repay_pretreat)

3、因为前置还款指令会有大量的重复记录,去重然后产生还款命令(aeghis_repay_cmd),同时删去aegis_repay_pretreat中的记录。

4、处理还款命令生产扣款命令。

5、处理扣款命令,调用支付宝受托。

大概需要4个定时任务调度。终于解决了问题了,也处理高并发场景,太爽了################################

真的没问题了么??在测试的时候发现,由于调度器会不停地抢锁,扫表,oracle吃不消啊!!!!!!!!!!

进一步优化,一般用的调度任务,除了Linux的crontab,再就是spring的quartz调度,当然支付宝有比较牛逼的分布式调度中心。但是鉴于优化访问oracle的性能,选用自己搞quartz。

开始了:

假设我有10台机器,他们都需要从同一个表中捞取数据,那么需要加锁,然后更改任务状态,别人就捞不到了。但是如果不停地捞取,频繁扫表,数据库性能极具下降,但是这种定时任务都是每时每刻在执行,如何解决?

首先做一个阻塞队列arrayBlockingQueue,然后先加锁然后捞数据,抢不到锁就sleep几秒,然后对捞取的数据判断,如果没有捞到,那么说明此时表中并没有多少数据,那可以再sleep,看起来没什么问题。

可不可以进一步优化,因为我们知道一般用到线程池,都需要关注他的coreThreadCount,maxThreadCount,队列长度。具体处理是当前线程数量小于coreThreadCount,则会创建线程,如果大于,则加入队列,如果放不进去创建线程,如果大于maxThreadCount抛异常。

所以,可以看到,如果线程比较忙的时候,阻塞队列数量会很多,线程压力会比较大。那么可以这样,每次处理判断下队列的长度,如果大于饥饿值就sleep,降低线程压力。

还能不能再进一步优化?

既然所有的处理都围绕着队列长度,捞取的数量,可不可以计算下捞取的数量,也就是因为每次捞取队列当前容量size - 队列当前长度length 的指令数量,那么,如果说捞取后,发现队列中的长度还是低于整个队列容量的1/3是不是表示此时表中并没有多少数据,仍然可以sleep以此降低扫表频率。

get it

------------------------------------------------------------------------

经过一番折腾,终于解决了!这里留下一个问题:如何解决抢锁频繁,更改状态会在机器重启或者发布时卡主指令如何处理?留给大家讨论下,欢迎交流。发完了之后,有些小伙伴问我,为啥处理这么复杂,在这里说一下,一般用户还款大概峰值是几百万比,但是在大促的时候洪峰大概上亿比。所以只能这样处理。

转载于:https://my.oschina.net/u/3203060/blog/818898

我在支付宝是如何处理高并发case的相关推荐

  1. 如何处理几十万条并发数据_Swoole 如何处理高并发以及异步 I/O 的实现

    Swoole 介绍 1.swoole提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis, 数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件 ...

  2. 如何处理高并发和单点故障

    如何处理高并发: 如果你确实有真才实学,在互联网公司里干过高并发系统,那你确实拿offer基本如探囊取物,没啥问题. 但是如果你要是真是干过高并发系统,面试官绝对绝对不会问这个问题,否则他就不太明智了 ...

  3. node和php处理高并发,node.js“多线程”如何处理高并发任务?,nodejs java 高并发

    node.js"多线程"如何处理高并发任务?node . js"多线程"是如何处理高度并发的任务的?,下面的文章介绍了使用nodejs"多线程&quo ...

  4. nginx如何处理高并发

    一.阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 1.同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步 当一个同步调用 ...

  5. RabbitMQ(mq) 如何处理高并发、负载均衡、消息幂等性、丢失、消息顺序错乱问题?

    目录 介绍: 1.连接器(connection): 2.信道.通道(channel): 3.交换机(exchange): 4.队列(queue): 以下通过两个例子,让我们先来对rabbitmq 有个 ...

  6. java支付宝支付_Java 高并发环境下的性能优化,揭秘支付宝技术内幕

    前言 高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动,定时领取红包等. 为了让业务可以流畅的运行并且给用户一个好的交互体验,我们需要根据业务场景预估达到的并发量等因素,来设计适 ...

  7. 一文教你如何处理高并发

    目录 前言 一.为什么要解决高并发问题 二.性能评估 计算峰值流量方法 本章结论 三.性能测试 测试目的 找到系统最高承受压力的临界点 找出系统中的短板 测试工具 简单测试 1.数据抓包 2.加压测试 ...

  8. 1808亿次,16倍的超越!谈支付宝红包的高并发挑战

    与传统意义上的红包相比,近两年火起来的"红包",似乎才是如今春节的一大重头戏.历经上千年时代传承与变迁,春节发红包早已成为历史沉淀的文化习俗,融入了民族的血脉.按照各家公布的数据, ...

  9. 云时代架构阅读笔记十三——你的系统如何处理高并发?

    1 从最基础的地方做起,优化我们写的代码,减少必要的资源浪费. a.避免频繁的使用new对象,对于整个应用只需要存在一个实例的类,我们可以使用单例模式.对于String连接操作,使用StringBuf ...

最新文章

  1. 「小程序JAVA实战」小程序我的个人信息页面开发(41)
  2. Storm源码阅读之SpoutOutputCollector
  3. 服务器虚拟机进不了暗黑3游戏,暗黑破坏神3无法初始化 D3D的解决方法
  4. 狄克斯特拉算法(入门)
  5. l298n电机驱动模块_带DRV8825驱动器模块和Arduino的控制步进电机
  6. WP8.1学习系列(第九章)——透视Pivot开发指南
  7. linux下gdb的简单使用
  8. Linux内核分析 - 网络[十二]:UDP模块 - socket
  9. html php上传图片验证判断,HTML_PHP实例:上传多个图片并校验的代码,单张的图片上传是不复杂的, - phpStudy...
  10. php 替换 tab,PHP 删除字符串中的空格和换行符终极方法 - 文章教程
  11. macos安装python3.6_在CentOS 7/Ubuntu 16.04/Debian 9/macOS上安装Python 3.6的方法
  12. vbs中的WScript.Network[属性与方法]
  13. 《OpenGL超级宝典》 - 源代码文件
  14. QT D:\搜狗输入法\SogouInput\Components\ 13:53:42: 程序异常结束。 13:53:42: T
  15. LoadRunner11完美破解
  16. 机器学习算法工程师面试问题
  17. 对企业来说,网络营销渠道与传统营销的渠道有何不同?
  18. 最新电销语音机器人完整版源码+含安装教程
  19. ONLYOFFICE历史版本开发技术之三
  20. MuMu模拟器开发者文档

热门文章

  1. 「启蒙教育」对婴幼儿的发展有怎样的影响,哪些益智产品是有效的?
  2. 手机摔了以后屏幕出现五颜六色的斑点是为什么
  3. $.ajax同步/异步(async:false/true)
  4. MogaFX—我附近的货币兑换
  5. 单片机的技术特点及应用系统
  6. 产品(设备)履历本系统 (概要)
  7. poi读取excel
  8. java公告栏js资源_JavaScript实现公告栏上下滚动效果
  9. 《深入理解计算机系统》读书笔记-02
  10. 【休闲益智】【HTML】抓船长,30s抓船长,看能抓几只