请问用Laravel做的商城,支付过程遇到高并发情况导致订单状态未处理成功 应采用哪些方案?
1. 运行环境
1). 当前使用的 Laravel 版本?
Laravel 5.4
2). 当前使用的 php/php-fpm 版本?
PHP 版本:7.3
php-fpm 版本:
没查到具体的版本。。如图
3). 当前系统
CentOS 8
4). 业务环境
开发环境,暂未加入负载均衡
5). 相关软件版本
2. 问题描述?
其实是之前的一个其他PHP 框架的项目,在短时间内大量用户进行支付的时候,钱都扣了,但是程序没有将订单状态改为已支付,导致会员开通失败。
3. 您期望得到的结果?
尽可能的让大量用户(比如一万人)同时进行支付时,确保订单信息不错乱。
4. 您实际得到的结果?
在短时间内大量用户进行支付的时候,钱都扣了,但是程序没有将订单状态改为已支付,导致会员开通失败
没用redis吗?
这可以理解为服务器需要支撑1w qps 了吧,单机怎么可能做得到
如果是遗留问题,你不想去改业务代码,最简单的解决方案如下:
updated_at
字段,使用乐观锁,在查询产品信息时,如果stock > 0
,更新库存,更新库存的时候添加where
字段,条件是updated_at
字段与查询产品信息时相同,如果相同,更新时间戳,并且扣掉对应库存,否则直接支付失败。每次更新
stock
时自动维护updated_at
时间戳就好了。用 Hyperf 重写这块
redis
应该可以解决绝大部分问题。用队列吧
支付成功,状态没变?是回调后,没有处理吗?
可以简单一些,在调起支付的时候,用redis做个限流,这样的话,回调的数量就大概在可控范围了。如果硬性要求必须支持大流量的话,那就加服务器,负载,换Hyperf 、easyswoole 框架或者go来重写这块业务
回调验签成功后放到队列处理其他更新状态等的逻辑
上个队列就可以满足需求了,laravel 自带的 databases队列,或者redis队列,支付成功后,把付款成功写入队列,开两个work进程去消费队列就好。你的问题是付款成功了,但是权益没有加上,使用队列最合适了
在异步回调那里加个队列应该够了...
Redis
SetNx
状态没修改说明异步回调没执行成功,回调可以放队列里处理,嫌速度慢就多开几个线程,我觉得更多是你服务器的瓶颈,配置太低了
对,有支付记录,但是支付状态没改成功,异步回调里没处理好。
redis的锁加一个,然后走队列,不行的话再加mq
商场类型的下单支付后,必须放到延迟队列里面去查询支付是否成功,及时,1分钟,3分钟 6分钟 10分钟...
异步回调放队列,另外我们在订单详情和列表会去查询微信支付状态,根据查询结果改状态
后端对下单这个地方限流。 订单加个中间状态,比如 “正在处理中” 。然后 微信的回调请求的参数 ,加入队列里处理。处理完再改为已支付等。