gpt4 book ai didi

mysql - 当事件循环等待数据库操作时,如何处理对 nodejs 服务器的传入请求

转载 作者:可可西里 更新时间:2023-11-01 08:23:26 32 4
gpt4 key购买 nike

我的 API 中有一个路由,例如,我们将其称为/users/:userId/updateBalance。此路由将获取用户当前余额,添加来自请求的任何内容,然后使用新计算的余额更新余额。像这样的请求每 30 分钟进入一个特定用户的服务器,所以直到最近,我认为并发问题是不可能的。

最终发生的事情是,某处发送的请求失败,并且仅在 30 分钟后再次发送,大约在另一个请求的一秒内。结果是,正如我在数据库中看到的那样,这两个请求都从数据库中获取了相同的余额,并且都添加了各自的金额。本质上,第二个请求实际上读取了过时的余额,因为它通常应该在请求 1 执行后执行。

为了更清楚地给出一个数字示例,假设请求 1 是向余额中添加 2 美元,请求 2 是向余额中添加 5 美元,用户的余额为 10 美元。如果请求并行执行,则用户余额将以 12 美元或 15 美元结束,具体取决于请求 1 或请求 2 分别先完成,因为两个请求都从数据库中获取了 10 美元的余额。然而,显然预期的行为是我们希望请求 1 执行,将用户余额更新为 12 美元,然后请求 2 执行并将余额从 12 美元更新为 17 美元。

为了更好地了解这个过程的整体执行情况:收到请求,调用一个函数,该函数必须等待来自数据库的余额,然后该函数计算新的余额并更新数据库,之后执行完成。

所以我有几个问题。第一个是, Node 在等待异步请求(如 MySQL 数据库读取)时如何处理传入请求。鉴于我观察到的结果,我假设当第一个请求正在等待数据库时,第二个请求可以开始处理?否则我不确定在像 Node 这样的单线程环境中如何体验这种异步行为。

其次,我该如何控制和预防它。我曾想使用带有 forUpdate 锁的 MySQL 事务,但由于当前编写代码的方式,这似乎是不可能的。有没有办法告诉 Node 某个代码块不能“并行”执行?或者任何其他选择?

最佳答案

你是对的,当 Node 等待数据库查询返回时,它将处理任何传入的请求并在第一个请求完成之前开始请求数据库调用。

防止此 IMO 的最简单方法是使用队列。路由处理程序可以将事件推送到队列(在 Redis、AWS SQS、RabbitMQ 等中)和您应用程序中的其他地方(甚至在完全不同的服务中),而不是直接在路由处理程序中处理余额更新会有一个消费者监听该队列中的新事件。如果更新失败,将其添加回队列的开头,增加一些等待时间,然后重试。

这样,无论您的第一个请求失败多少次,您的余额都将是正确的,并且对该余额的未决更改将以正确的顺序排列。如果队列中的事件反复失败,您甚至可以向某人发送电子邮件或通知以查看它,当问题已解决时,待处理的余额更改将添加到队列中,一旦它已修复,一切都将得到正确处理。

您甚至可以读取该队列并向您的用户显示信息,例如告诉用户余额有待更新,因此它可能不准确。

希望这对您有所帮助!

关于mysql - 当事件循环等待数据库操作时,如何处理对 nodejs 服务器的传入请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56344533/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com