ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2019-12-10 22:15:41  阅读:286  来源: 互联网

标签:node-js asynchronous mysql


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

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

为了更清楚地给出一个数值示例,假设请求1将2美元添加到余额中,请求2则添加5美元,而用户的余额为10美元.如果请求并行执行,则根据请求1或请求2首先完成,用户余额将分别为$12或$15,因为两个请求都从DB提取了$10的余额.但是,显然预期的行为是我们希望执行请求1,将用户余额更新为$12,然后请求2执行并将余额从$12更新为$17.

为了更好地了解此过程的整体执行情况:接收了请求,调用了一个函数,该函数必须等待DB的余额,然后该函数计算新的余额并更新db,然后执行完成了.

因此,我对此有一些疑问.第一个是,节点在等待异步请求(如MySQL数据库读取)时如何处理传入的请求.根据我观察到的结果,我假设当第一个请求等待数据库时,第二个请求可以开始处理吗?否则,我不确定在节点等单线程环境中如何经历这种异步行为.

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

解决方法:

没错,当节点等待数据库查询返回时,它将处理所有传入请求,并在第一个请求完成之前启动请求数据库调用.

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

这样,无论您的第一个请求失败多少次,您的余额都将是正确的,并且对该余额的未决更改将以正确的顺序进行.万一队列中的事件反复失败,您甚至可以向某人发送电子邮件或通知以进行查看,而问题已解决的同时,余额的更改将添加到队列中,并且一旦固定,一切都会正确处理.

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

希望这可以帮助!

标签:node-js,asynchronous,mysql
来源: https://codeday.me/bug/20191210/2104478.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有