REST是否仅限于乐观并发控制?


9

语境

由于REST体系结构样式的无状态性(涉及每个请求完全独立),导致服务器从不存储有关客户端的任何信息。

因此,悲观并发控制不合适,因为这将要求服务器存储哪个客户端获得资源锁定。然后在Etag标头的帮助下使用乐观并发控制。(顺便说一句,正如我在那儿问的/programming/30080634/concurrency-in-a-rest-api

问题

乐观并发控制机制的主要问题在于,您始终允许所有客户端执行任何操作。

我想避免这种情况,而不会破坏REST的无状态原则。我的意思是,所有客户端都无法随时执行任何操作。

在我看来,采用半乐观并发控制机制是可能的,例如:

  • 客户可以请求令牌
  • 只能生成一个令牌,并且有效期有限
  • 要对资源(例如POSTPUT)执行操作,客户端必须将此令牌作为请求正文(或标头?)的一部分提供。没有令牌的客户端无法执行这些操作。

它与开放式并发控制非常相似,不同之处在于,只有一个客户端可以执行某些操作(获得令牌的操作)……与“所有客户端可以执行所有操作”相反。

这种机制是否与REST架构风格兼容?它打破了它的任何约束吗?我当时想问一下SO,但这似乎是一个与软件设计有关的高级问题。


1
实际上,这非常简单:您必须Transaction显式地将其建模为资源。
约尔格W¯¯米塔格

它会发生什么变化?不知道您的评论。我不是在进行事务的并发控制,而是要对客户端说:“现在,您绝对确定没有人会更改资源”(因为它具有唯一的令牌)。
AilurusFulgens 2015年

1
有什么区别?一方面,您可以使用Etag来检查谁可以更新“当前”版本。如果冲突,则必须更新版本,然后再进行更新。另一方面,您具有“锁定”机制:一个被允许,其他必须等待。听起来差不多。第二种方法的缺点:2个请求-1个用于锁定,1个用于更新。在最佳情况下,您只能通过Etag方法进行一次更新。
Thomas Junk 2015年

好吧,通常来讲并发控制……“输掉比赛”的第二个总是必须等待(出于不同的原因,我同意)。与Etag?的区别 随着Etag你永远不会相信你的操作就完成了,你可以有一个情况下,你将永远不会执行任何操作。使用锁,您至少可以执行操作。因此,拥有一个简单的锁只是在可能发生“高冲突”和“罕见冲突”的环境之间进行调整。
AilurusFulgens 2015年

Answers:


3

在等待用户交互时,您永远都不应(就像从没有一样)锁定任何资源。

在某些时候,您的某些用户将休假一个漫长的周末,从而使一些重要记录被锁定。

啊,但是您不会让这种事情发生,因为您有一些聪明的超时/死锁解决方案。然后在某个时候这将变得非常错误,并且收到一个不错的“您的小部件已订购”消息的用户将在服务台尖叫,要求知道为什么未交付他的小部件。

大多数人可以处理“很抱歉其他用户刚刚订购了此零件”消息。


您解释得很好。尽管我对您的第一句话并不完全相信:在某些时候,您将保证除您可以执行命令外,没有其他人可以执行。但是,您的最后一句话是一个很好的总结,在99%的情况下都是这样。
AilurusFulgens 2015年

1
如果您需要锁定特定用户的记录,请在应用程序级别执行。要么使用简单的“ LockedBy”属性,要么使用一些更复杂的版本控制和工作流机制。
詹姆斯·安德森

“应用程序级别”是什么意思?如果在资源上添加“ LockedBy”属性,则将有关客户端的信息存储在服务器上。也许我不理解您的评论。如果您可以提供一些详细信息,那就太好了!
AilurusFulgens 2015年

1
@AilurusFulgens-您将LockedBy属性(可能还添加了LockedOn时间戳)添加到数据库中。在应用程序代码中,只要客户端启动更新交互,就可以设置用户名和时间。你取消它,当客户端已经完成-那么你需要制定出一些业务规则,解决冲突和超时等
詹姆斯-安德森

2

使用令牌在API中非常常见,这些令牌通常作为标头发送,并且具有清晰的生命周期。例如考虑OAuth。

无论您使用哪种编程语言或框架,REST API都是相似的。

我可以想到要限制并发性的几种情况,其中两种是:

  1. 多个客户端更新相同的资源,例如数据库行。例如:两个并发请求,一个删除一条记录,另一个尝试更新同一条记录。根据您的数据库及其设置方式,由于数据不同或不存在,您可能会锁定记录或进行无效操作。

  2. 使用该API执行特殊操作的超级用户或管理员。


在这些情况下该怎么办?

  1. 使用数据库中的事务,单例,锁和类似的机制来同步对资源的访问。

  2. 令牌可能会起作用,我认为如果不存储有关客户端的信息,而仅存储有关令牌本身的信息,会更好。第一步,您可以验证用户并分配令牌。然后,只需验证令牌是否有效即可。使用可以解密的令牌以获得更多信息。您可以存储是否是特殊令牌,并且一次只能启用。这样,您可以验证令牌,而不是用户。

我希望这有帮助。


是的,我期望获得有关令牌和OAuth机制相似性的回应。尽管最后一个专用于身份验证。我没有弄清楚您的情况1. REST API中处理并发的棘手部分是保持无状态约束...这意味着服务器不存储有关客户端的信息。您的方案2正是我当前正在做的!:)
AilurusFulgens 2015年

我回答了你的问题吗?
Pablo Granados 2015年

不好意思 我赞成您的回答,因为它很好地概述了问题,但不幸的是,imo,它并没有真正解决问题。
AilurusFulgens 2015年

0

真的,REST本身太原始了。您可以开始使用REST,但是最终,您的丰富应用程序将需要具有联接的查询和具有事务的更新。每个尝试自行添加这些内容的开发人员都容易出错并且前后不一致。幸运的是,有一个新兴的标准叫做OData。它在REST之上分层,并提供(1)查询语言,该语言允许使用导航属性进行简单联接(而不必公开外键),以及(2)包括原子更改集的批处理。

参见此处了解(1)https://stackoverflow.com/a/3921423/471129,以及

参见此处和(2)https://stackoverflow.com/a/21939972/471129

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.