REST和事务回滚

时间:2015-10-11 02:30:50

标签: rest transactions

我有一些不同的REST服务,这些服务托管在使用不同数据库的不同服务器上。我有一些RESTful服务,它们在应该是一个事务单元中调用上面的多个这样的服务。如果这些RESTful服务中的任何一个失败,我们最终会遇到数据一致性问题。是否有一种巧妙的架构方式来协调回滚?或者让交易经理走的路?

作为一个简单的例子,RESTful服务1有一个POST请求,它将thingamajig的项目数减少1。 RESTful服务2发送付款。如果服务2失败,我们如何在没有新的RESTful退款服务的情况下干净地实施服务1的回滚(如果必须要这样做,那就没关系)。我正在寻找上述问题的架构答案,这符合REST原则。

3 个答案:

答案 0 :(得分:7)

您的回答:https://stackoverflow.com/a/1390393/607033您无法使用事务,因为通过REST,客户端维护客户端状态,服务器维护资源状态。因此,如果您希望客户端维护资源状态,那么它不是REST,因为它会违反stateless constraint。违反无状态约束通常会导致糟糕的可伸缩性。在这种情况下,它将导致错误的水平可伸缩性,因为您必须在实例之间同步正在进行的事务。所以,请不要尝试在REST服务之上构建多阶段提交。

可能的解决方案:

  • 您可以坚持即时一致性并仅使用     一个Web服务而不是两个。通过数据库,文件系统等资源,多阶段提交是必需的。当您分解更大的REST服务并将这些资源的使用转移到多个较小的REST服务中时,如果您错误地执行此拆分,则可能会出现问题。这是因为其中一个REST服务将需要一个它无权访问的资源,因此必须使用另一个REST服务来访问该资源。这将迫使多阶段提交代码移动到更高的抽象级别,达到REST服务的级别。您可以通过合并这两个REST服务并将代码移动到它所属的较低抽象级别来解决此问题。
  • 使用REST与最终一致性的另一种解决方法,以便您可以立即接受202响应,并且您可以稍后处理接受的请求。如果选择此解决方案,则必须通过开发应用程序来了解REST服务并非始终保持同步。 OFC。这种方法只适用于内部REST服务,通过它可以确保客户端在REST服务不可用时重试,因此如果您编写并运行客户端代码。
  • 另一种可能是存储每笔交易的最丑陋的解决方法     作为资源,您可以POST提交和回滚。我认为这种可能的解决方案不可行,因为它会违反统一的接口约束。我们会使用POST /transactions/ {resource: "/forums/12/messages/45", method: "PUT", data: "..."}POST /transactions/1/commit代替PUT /forums/12/messages/45

答案 1 :(得分:1)

分布式事务很复杂,需要每个参与系统都支持回滚的概念。对于您的服务,他们每个人都必须支持某种形式的回滚。在分布式系统中协调类似这样的事情可能不实用或不可取用同步方式。在这种情况下,您可能希望异步回滚,系统最终会在未来某个时间点达到一致性。显然还有很多其他细节(超时,错误处理,重试等)。

有关最终一致性的更多详细信息,请查看维基百科条目here

答案 2 :(得分:0)

基本上问题是你需要在一个环境(HTTP)中使用默认情况下不是事务性的事务 - 在DB意义上(因为在HTTP中事务是一个成功的请求 - 响应周期)。

@leeor响应的内容完全正确,我想添加的是我如何从设计网站解决问题。

所以你需要一个端点,可能是/transactions。通过POST方法,您可以添加一个不可变的新事务(包含所有必需的详细信息) - 创建后,您只能通过GET方法询问数据/状态。可以更新事务状态/数据的只是服务器本身。

在幕后(在创建事务期间),应创建参与事务的每个资源的快照(稍后可以反转)。然后应该开始执行所有操作,如果发生任何故障,应该反转所有快照。你没有提到任何技术,所以很难提出合理的建议。您需要的是全面的日志记录。