如何处理RESTful应用程序中的竞争条件?

时间:2012-08-21 15:37:04

标签: java web-services design-patterns rest

以下是我的RESTful网络应用程序中发生的情况:

  1. HTTP请求进入
  2. 应用程序开始构建响应,其中包含一些初始数据
  3. 另一个请求更改了步骤2中使用的数据
  4. 第一个请求了解数据已过期
  5. 该怎么办?请求失败并将错误返回给客户端?或者它应该从头开始(花费的时间比客户期望的多)?

5 个答案:

答案 0 :(得分:4)

恕我直言,您应该将REST请求视为非常接近您处理数据库事务的方式:

  • 要么确保在执行一些实际操作之前锁定需要锁定的内容
  • 或准备在并发问题上失败/重试

这通常可以传递给数据库事务 - 取决于您的请求的工作量和数据库工作量。

答案 1 :(得分:1)

从我的观点来看,你的问题是一样的:
“如果我尝试从数据库中读取数据,而另一个事务尝试执行写操作,则会阻止。但是当我完成读取操作时,我将错过将由新事务填充的新数据在我读完之后。“ 这是一个不好的思考方式。您应该确保客户端在响应中获得一致的数据。如果数据在获得原始方法无问题的响应时已更新 您的问题是数据当前已更新,我碰巧知道。如果数据在响应消失后立即更新怎么办? 恕我直言选择最符合您要求的最简单的解决方案 客户应更频繁地“轮询”以确保他们始终拥有最新的数据副本

答案 2 :(得分:1)

我认为一个很好的起点是CouchDB使用的并发模型。实质上:

  • 每个请求都是孤立处理的,即不受其他并发请求的影响。这意味着当您开始处理请求时,您需要能够获得数据库的一致快照,大多数DBMS系统都支持这种快照的概念。
  • GET请求总是成功,并在提交时返回系统状态,忽略任何后续更新。
  • GET请求返回相关资源的修订版ID,必须将其作为字段包含在任何后续PUT请求中。
  • 在PUT请求中,将根据数据库中的最新修订ID检查提交的修订ID。如果它们不匹配,则返回错误代码,在这种情况下,客户端必须重新获取最新版本并重新应用它们所做的任何更改。

更多阅读:

http://wiki.apache.org/couchdb/Technical%20Overview#ACID_Properties http://wiki.apache.org/couchdb/HTTP_Document_API#PUT

答案 3 :(得分:1)

假设它不是关于数据库事务,并且说每个步骤都涉及分布式长时间运行的进程。

在这种情况下,应该向客户端发送适当的响应(类似于409/410 http代码),其中的详细信息表明此请求不再有效,客户端应该再次尝试。重试可能会以循环结束或最坏情况最终导致客户端不知道。

例如,当您在线预订酒店/机票时,您会收到回复,说明价格已经发生变化,您需要再次提交以新价格购买。

答案 4 :(得分:-1)

严格来说,竞争条件是一个错误。竞争条件的解决方案没有共享数据。如果对于给定的用例不能避免这种情况,那么先来先服务通常会有所帮助:

第一个请求锁定共享数据,第二个请求等待第一个请求完成。