java - REST 服务和竞争条件

标签 java rest race-condition

让我们想象一个问题: 我有一个 REST 服务,它是使用 Java/MySQL/Spring 和 HTTP/JSON 技术实现的。 REST 服务的客户端是移动应用程序。 因此,有人可能会反编译代码并获得 REST 服务的 API。 (是的,代码被混淆等,但无论如何)。

问题:有一个 POST 方法可以向应用程序的其他用户汇款。 我担心有人可以获得 API,编写机器人并每秒发出 500 或 5,000 甚至 50,000 次此 POST 请求。 结果,他可能会发送比他实际拥有的更多的钱,因为如果同时处理 1000 个请求,那么余额检查可能是 所有 1000 个请求都成功,但是一个帐户上的实际金额可能只够,比方说,50 个请求。

所以,基本上,它更像是多线程的标准“竞争”条件。 问题是,我有多个服务器,而且它们之间无论如何都不相关。 因此,300 个请求可以到达服务器 A,300 个请求可以到达服务器 B,其余请求可以到达服务器 C。

我最好的想法是使用类似“SELECT ... FOR UPDATE”的东西并在数据库级别同步。 但是,我想考虑其他解决方案。

有什么想法或建议吗?

最佳答案

您有几个选择:

  1. 依靠数据库的 ACID 实现(在您的例子中是 MySQL)。假设您使用的是 InnoDB 引擎,您需要选择正确的事务隔离级别 (SET TRANSACTION syntax) 并结合正确的锁定读取机制 (SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE Locking Reads)。您需要很好地理解这些概念才能做出正确的选择。即使没有锁定读取,简单地使用正确的隔离级别也可能已经防止了竞争条件。缺点是您正在牺牲一致性以换取可伸缩性并将您的应用程序绑定(bind)到 RDBMS 数据库,因此您将更难迁移到 NoSQL 等。

  2. 将您的后端分解为网络层和服务层(atk 在评论中建议的选项)。这将允许您独立扩展 Web 层实例,同时保留单个服务层实例。拥有单个服务层实例可以使用 Java 同步机制,例如 synchronized block 或 ReadWriteLock。尽管此解决方案可行,但我不推荐它,因为它会降低服务层的可扩展性。

  3. 这是对前一个选项的增强。您可以使用 Distributed lock manager而不是内置的java同步机制。它将允许您独立扩展 Web 层和服务层。

关于java - REST 服务和竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30271285/

相关文章:

java - iPhone 上的 Cocoa Java 应用程序

java - @RequestMapping 不起作用 - 没有找到处理程序方法

python - Django ArrayField 追加,避免竞争条件

web-services - 当 session token 无效时,我应该使用什么状态代码?

java - 构建 URI 以使用 REST 服务

java - 我该如何解决这个竞争条件?

cassandra - 如何使用 cassandra 更新处理竞争条件?

java - Mockito:验证来自内部匿名类的方法调用

java 访问修饰符 : no-modifier vs "default"

Java Applet Commented Applet 标签