8

这是我的 RESTful Web 应用程序中发生的事情:

  1. HTTP 请求进来
  2. 应用程序开始构建响应,其中包含一些初始数据部分
  3. 另一个请求更改了步骤 2 中使用的数据
  4. 第一个请求就知道数据过期了

它应该怎么做?请求失败并向客户端返回错误?还是应该从头开始(花费比客户预期更多的时间)?

4

5 回答 5

4

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

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

很多时候,这实际上可以传递给数据库事务 - 取决于您的请求所做的非数据库工作的数量和内容。

于 2012-08-21T15:41:24.383 回答
3

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

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

更多阅读:

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

于 2012-08-21T16:26:23.640 回答
2

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

在这种情况下,应向客户端发送适当的响应(例如 409/410 http 代码),其中包含表明此请求不再有效且客户端应重试的详细信息。重试可能会陷入循环,或者最坏的情况最终会导致客户不知道。

例如,当您在线预订酒店/机票时,您会收到回复说价格已更改,您需要再次提交以使用新价格购买。

于 2012-08-24T20:36:01.430 回答
1

从我的角度来看,您的问题与以下相同:
“如果我尝试从数据库中读取,而另一个事务尝试写入,它将阻塞。但是当我完成读取时,我会错过新数据将由我读取后传入的新事务填充。”
这是一种不好的思考方式。您应该确保客户端在响应中获得一致的数据。如果在他们得到响应时数据已经更新,则不是原始方法的问题。
您的问题是数据当前已更新,我碰巧知道。如果在响应传出网络后立即更新数据怎么办?
恕我直言,选择适合您要求的最简单的解决方案。
客户端应该更频繁地“轮询”以确保他们始终拥有最新的数据副本

于 2012-08-21T15:44:15.870 回答
-1

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

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

于 2012-08-21T15:43:30.843 回答