我不知道我应该把我的问题和问题放在哪里,但我会在这里试一试。
前一段时间,我有一个小项目,用户可以把硬币花在思考上。这些硬币作为余额存储在mysql数据库的用户帐户上。前端已使用连接到后端 socket.io
节点应用程序使用常规的 mysql
模块。
问题:不幸的是,过了一段时间,我发现可以使用socket.io连接(或者多次打开网站以获得相同的结果)来淹没/垃圾邮件节点应用程序,以减慢mysql查询的速度。这就是为什么有可能花掉一个用户两次或更多的硬币。
正常的工作流程如下:
Request to DB
check balance
if balance > 0
spend coins
reduce coins in DB
else
reject
请求结束
如何花两次硬币:(问题)
Request to DB
Request to DB
check balance
check balance
if balance > 0
if balance > 0
spend coins
spend coins
reduce coins in DB
reduce coins in DB
else
reject
Request end
Request end
到那时,就有可能在余额被更新之前到达代码以使用这些硬币。
问:怎么可能阻止用户做这样的事情?使用请求限制器只适用于使用相同ip的人,所以scriptkiddys应该不能达到我上面提到的内容。如果人们使用不同ip的小型僵尸网络呢?
如果我能解决这个问题,我可以重新开始这个项目。
1条答案
按热度按时间mftmpeh81#
一种解决方法是使用
select for update ... where user = XXX
锁定check balance
.另一个解决方案是添加
version
列。那么get balance and version
,(假设verison是n),spend
,reduce coins and set version= n+1 where version == n
,则后面的填充失败。在这个解决方案中,您应该spend coins
过了一段时间reduce succeeded.
.因为我不熟悉socket.io,所以这些只是作为参考的通用解决方案。