【问题标题】:Should I Use A Queueing System To Handle Payments?我应该使用排队系统来处理付款吗?
【发布时间】:2018-06-12 13:32:57
【问题描述】:

我使用SlimStripe's PHP Library 在我的应用程序中处理付款。

一切都很好,但是直到最近,我发现我的系统中存在一个令人担忧的故障,我认为这可能是一个比我想象的要大得多的问题。在我的逻辑中,在支付流程的三个独立检查点,我检查了我的(MySQL)数据库中的库存,以确保用户购买的产品没有超过可用的数量。

但是,当多个用户在大约 500 毫秒 内发出请求时,支付系统似乎会同时处理这些请求,从而导致一系列问题,包括库存不正确和不平衡,对成功付款的虚假用户确认。

通过一些尽职调查,我将解决方案缩小到两个选项(尽管我可能会卖空自己):

1) 使用Queueing System,据我了解,它将对这些请求进行排队并一次处理一个,创建先到先得的排序原则。

2) 将一些中间件附加到每个请求上,这些中间件将充当队列并尝试同步处理每个请求(尽管这可能与我已有的类似)

话虽如此,对这些选项有什么建议/意见吗?显然,您可以完全放弃我的理念,为我指明不同的方向。

【问题讨论】:

  • 我绝对认为具有某种实时确认请求已处理的排队系统是解决此问题的完全有效的方法。如果我分享了您的担忧,我会使用与 websocket 相结合的排队系统,它告诉我的前端后端已经从头到尾处理了请求。这也给你带来了很多很酷的好处——重试、响应能力、对比特币等事物的异步处理等。不过,Stripe 也是同步的,所以你总是可以在处理完付款后定期进行清理以确保你的库存在那里。
  • 你应该考虑使用事务。还要确保您的数据库已正确索引并且可能具有(另一个)唯一索引。您使用的是哪个 RDBMS?记得@Niner me。
  • 使用 MySQL @Funk Forty Niner
  • @JaredGarcia 好的,谢谢。那么您如何看待使用交易?你有没有考虑过,还是我完全错过了目标?
  • @JaredGarcia 那么,您的数据库确实被正确索引了吗?这个问题(对我来说)听起来更像是与数据库相关而不是特定于 Stripe 的问题。似乎没有人解决这个问题,至少没有看到一个公认的答案。所以从某种意义上说,你的问题可能是基于意见的,而且过于广泛,但对我来说还不清楚。也许我可能也没有抓住这个问题,而且我还远远不够。

标签: php queue stripe-payments payment-gateway payment


【解决方案1】:

所以如果我理解主要问题是你害怕有人购买已经售出的产品(此时付款正在处理中)......

我认为你应该放弃这个排队系统的想法——因为这不是线索。线索就是你的商店逻辑。

我不知道你的商店是如何运作的,但从逻辑的角度来看,产品应该在客户点击发送订单的那一刻被锁定(分配),而不是在付款过程之后。因为不是每次付款都可能成功(如果客户想用条纹或其他付款方式重试不成功的付款怎么办?)。

【讨论】:

  • 我明白了,我的商店逻辑相当简单。就像我说的那样,我在三个不同的检查点检查可用性,1)当用户选择结帐按钮时,发送一个 Ajax 请求以检查可用性,2)在输入成功的支付凭据之后 & 3)在请求命中条纹 API 之前.
  • 直到通过条带成功捕获付款后,我才锁定产品,如果没有,则用户可以重试。
  • 我同意@Michal G - 您必须将该项目标记为“保留”并将其与付款信息相关联。考虑一个时间戳“保留到”并在 SQL 中检查它。如果从未付款,则锁定会自行超时。只需确保在付款完成后标记为“已售出”即可。
  • @Lars Stegelitz 我明白了这种方法,但是这不会陷入同一个问题,即让多个用户同时锁定一个项目并可能同时成功签出可能不可用的项目跨度>
  • 如果锁定实施正确,则不会。主题是“mutex”、“semaphore”或“Critical Section”,它们专门用于处理这些情况(竞争条件)。使用通用数据库,您可以自己实现某些东西(具有该部分的唯一键的表。创建记录->您拥有锁。如果创建失败->其他人持有该部分的锁。只有在您获得时才采取行动锁。释放锁 -> 删除记录)。我已经为我正在工作的浏览器游戏实现了类似的东西,但我们经常遇到这些问题。
【解决方案2】:

使用 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

事务是一组顺序的数据库操作操作,它的执行就像它是一个单独的工作单元一样。换句话说,除非组内的每个单独操作都成功,否则事务将永远不会完成。如果事务中的任何操作失败,则整个事务都会失败。

【讨论】:

    【解决方案3】:

    我听说过很多关于使用排队系统的开发人员的恐怖故事,所以我绝对不建议这样做。先到先得的原则通常会导致在代码到位之前很难发现的错误——我知道的一位开发人员特别使用类似的系统创建了一家商店,结果发现许多客户最终得到了随机商品在他们的购物车中或到付款结束时才能确定没有物品库存。

    相反,我会使用使用 jQuery 或 Javascript 或 PHP 库的“事件侦听器”来确保在结帐过程中,如果数据库中的某些内容发生更改,那么 UI 将向用户指示库存不同或不可用。

    【讨论】:

    • 我明白了,我的商店逻辑相当简单。就像我说的那样,我在三个不同的检查点检查可用性,1)当用户选择结帐按钮时,发送一个 Ajax 请求以检查可用性,2)在输入成功的支付凭据之后 & 3)在请求命中条纹 API 之前.
    • 这绝对适用于您的应用程序,但可扩展性可能会成为一个大问题。即使它会稍微降低您的性能,也值得让某些东西始终等待数据库更改。因为正如您所指出的,库存可能会在检查点之间的任何时间发生变化。
    【解决方案4】:

    我认为您的问题与您的支付提供商无关。这是你的商店逻辑。我会做以下事情:

    1. 用户点击产品添加到购物车
    2. 产品进入“结帐”列表,您商店中的可用数量减少了 1
    3. 那么我们有两种可能:
      • 用户付款成功完成结帐=>您可以保留您的产品总金额
      • 用户中止结帐 => 您必须在特定时间(例如 5 分钟)后增加产品的总量

    如果您尝试在电影院购买座位,则必须在 5 分钟内完成结帐(向用户显示倒计时),否则预订将丢失,其他人可以预订座位。

    【讨论】:

    • 这是一个很好的方法,但是如果只有 5 个席位,而两个用户同时购买所有 5 个席位,那会不会还是会造成一些摩擦?
    • 肯定会的。但是在不知道这家店卖的是什么产品的情况下,我找不到解决办法。当然,您也可以向第二位用户显示预留了一些座位,这些座位将在 5 分钟后释放,或者您可以缩短预留时间。
    【解决方案5】:

    我想建议另一种方式来做到这一点,这就是我们在商店中处理付款和库存的方式。主要问题出现在大批量销售期间,我们使用库存管理解决方案处理黑色星期五和网络星期一的销售。

    您必须确保以下步骤同时付款

    1. 您应该在用户即将购买之前检查可用库存 进入支付流程。您可以通过将这些数据保存在 Redis 中来做到这一点,而不是每次都查询数据库。每当下订单时,它都会更新 Redis 中的库存条目以保持同步。
    2. 当您要致电支付网关以检查可用库存并提前处理(如果可用)时,否则会提示 用户。
    3. 当用户完成支付时,从数据库交易中的库存中扣除购买数量并使用锁。如果交易不 成功要么退还付款,要么由您决定 是否订购缺货产品。

    希望对你有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 2013-08-29
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多