我正在使用Slim与Stripe's PHP Library一起处理我的申请中的付款。
一切都很顺利,但直到最近,我发现我的系统中出现了一个令人担忧的错误,我认为这可能是一个比我想象的更大的问题。在我的逻辑中,在支付过程的三个独立检查点,我检查我的(MySQL)数据库中的库存,以确保用户不会购买比可用产品更多的产品。
但是,当多个用户在彼此大约 500ms 之间发出请求时,支付系统似乎会同时处理这些请求,从而导致一系列问题,包括错误和不平衡的库存,假用户确认付款成功。
通过一些尽职调查,我已经将解决方案缩小到两个选项(尽管我可能会卖空自己):
1)根据我的理解,使用Queueing System将这些请求排队并一次处理一个,创建一个先到先得的分类。
2)将一些中间件附加到每个将充当队列的请求上并尝试同步处理每个请求(尽管这可能类似于我现有的请求)
现在有了这些说法,对这些选项的任何建议/意见?并且显然可以完全废弃我的思想,并指出我的方向不同。
答案 0 :(得分:1)
所以,如果我理解主要问题是你害怕有人购买已售出的产品(此时正在处理付款)......
我认为你应该留下这个排队系统的想法 - 因为这不是这里的线索。线索是你店铺的逻辑。
我不知道您的商店是如何运作的,但从逻辑的角度来看,产品应该在客户端发送订单时锁定(分配),而不是在付款过程之后。并非每笔付款都可能成功(如果客户想用条纹或其他付费方式重试不成功的付款会怎样?)。
答案 1 :(得分:1)
使用TRANSACTIONS对此有利,因为看起来你已经面临所谓的竞争条件。
从https://www.w3resource.com/mysql/mysql-transaction.php拉出来,我引用:
事务是包含一个或多个SQL语句的逻辑工作单元。事务是可以提交或回滚的原子工作单元。当事务对数据库进行多次更改时,要么在提交事务时所有更改都成功,要么在事务回滚时撤消所有更改。
事务以第一个可执行SQL语句开头。事务在提交或回滚时结束,或者使用COMMIT或ROLLBACK语句显式结束,或者在使用DDL(数据定义语言(DDL)来管理表和索引结构以及CREATE,ALTER,RENAME,DROP和TRUNCATE语句时隐式)是命名一些数据定义元素)发布语句。
在交易期间锁定表将有助于防止竞争条件。
从同一资源中拉出来:
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type:
READ [LOCAL]
| [LOW_PRIORITY] WRITE
UNLOCK TABLES
更多信息和语法可以在(官方)MySQL网站上找到:
“关于交易”,来自https://www.informit.com/articles/article.aspx?p=29312
事务是一组连续的数据库操作操作,就像它是一个单独的工作单元一样。换句话说,除非组内的每个单独操作都成功,否则交易永远不会完成。如果事务中的任何操作失败,整个事务将失败。
答案 2 :(得分:0)
我听到许多关于开发人员使用排队系统的恐怖故事,所以我肯定会建议不要这样做。先到先得的原则通常会导致在代码到位之前难以捕获的错误 - 我所知道的一位开发人员使用类似的系统创建了一个商店,但却发现很多客户最终都是随机商品在他们的购物车中或到付款结束,以确定没有物品有库存。
相反,我会使用jQuery或Javascript或PHP库的“事件监听器”来确保在结账过程中如果数据库中的某些内容发生了变化,那么UI会向用户表明库存不同或不可用。 / p>
答案 3 :(得分:0)
我认为您的问题与您的付款提供商无关。这是你的店铺逻辑。我会做以下事情:
如果您尝试在电影院中购买座位,则必须在5分钟内完成结账(向用户显示倒计时),否则预订将丢失,其他人可以预订座位。
答案 4 :(得分:0)
我想建议另一种方法,这就是我们处理商店付款和库存的方式。主要问题出现在大批量销售期间,我们通过库存管理解决方案处理黑色星期五和网络星期一销售。
您必须确保执行并发付款的以下步骤
希望这会对你有所帮助。