简体   繁体   English

与Hibernate的乐观/悲观锁定并发的好策略/解决方案

[英]A good strategy/solution for concurrency with hibernate's optimistic/pessimistic locking

Let's presume that we have an application "mail client" and a front-end for it. 假设我们有一个应用程序“邮件客户端”和一个前端。

If a user is typing a message or editing the subject or whatever, a rest call is made to update whatever the user was changing (eg the receivers) to keep the message in DRAFT. 如果用户正在键入一条消息或正在编辑主题或其他内容,则将进行休息呼叫以更新用户正在更改的内容(例如接收者),以将消息保留在DRAFT中。 So a lot PUT's are happening to save the message. 因此,很多PUT正在保存消息。 When closing the window, an update of every editable field happens at the same time. 关闭窗口时,同时会更新每个可编辑字段。 Hibernate can't handle this concurrency: Each of those calls retrieve the message, edit their own fields and try to save the message again, while the other call already changed it. Hibernate无法处理这种并发性:每个调用都检索消息,编辑自己的字段并尝试再次保存消息,而另一个调用已经更改了消息。

I know I can add a rest call to save all fields at the same time, but I was wondering if there is a cleaner solution, or a decent strategy to handle such cases (like for example only updating one field or some merge strategy if the object has already changed) 我知道我可以添加一个rest调用来同时保存所有字段,但是我想知道是否有一种更干净的解决方案,或者一种合适的策略来处理此类情况(例如,如果仅更新一个字段或某些合并策略,对象已更改)

Thanks in advance! 提前致谢!

The easiest solutions here would be to tweak the UI to either 这里最简单的解决方案是将UI调整为

  • Submit a single rest call during email submission that does all the tasks necessary. 在电子邮件提交期间提交一个单独的休息电话,该电话完成所有必要的任务。
  • Serialize the rest calls so they're chained rather than firing concurrently. 序列化其余调用,以便将它们链接在一起,而不是同时触发。

The concern I have here is that this will snowball at some point and become a bigger concurrency problem as more users are interacting with the application. 我在这里担心的是,随着更多用户与应用程序进行交互,这将在某个时候滚雪球并成为一个更大的并发问题。 Consider for the moment the potential number of concurrent rest calls your web infrastructure will have to support alone when you're faced with a 100, 500, 1000, or even 10000 or more concurrent users. 现在考虑一下当您面对100、500、1000甚至10000个或更多的并发用户时,您的Web基础结构可能需要单独支持的潜在并发呼叫数。

Does it really make sense to beef up the volume of servers to handle that load when the load itself is a product of a design flaw in the first place? 当负载本身首先是设计缺陷的产物时,增加服务器的数量来处理该负载真的有意义吗?

Hibernate is designed to handle locking through two mechanisms, optimistic and pessimistic. Hibernate旨在通过乐观和悲观两种机制处理锁定。

Optimistic Way 乐观的方式

  1. Read the entity from the data store. 从数据存储中读取实体。
  2. Cache a copy of the fields you're going to modify in temporary variables. 在临时变量中缓存要修改的字段的副本。
  3. Modify the field or fields based on your PUT operation. 根据您的PUT操作修改一个或多个字段。
  4. Attempt to merge the changes. 尝试合并更改。
  5. If save succeeds, you're done. 如果保存成功,则完成。
  6. Should an OptimisticLockException occur, refresh the entity state from data store. 如果发生OptimisticLockException ,请从数据存储刷新实体状态。
  7. Compare cached values to the fields you must change. 将缓存的值与您必须更改的字段进行比较。
  8. If values differ, you can assert or throw an exception 如果值不同,则可以断言或引发异常
  9. If they don't differ, go back to 4. 如果没有差异,请返回4。

The beautiful part of the optimistic approach is you avoid any form of deadlock happening, particularly if you're allowing multiple tables to be read and locked separately. 乐观方法的妙处在于,您可以避免发生任何形式的死锁,尤其是当您允许多个表分别读取并锁定时。

While you can use pessimistic lock options, optimistic locking is generally the best accepted way to handle concurrent operations as it has the least concurrency contention and performance impact. 尽管可以使用悲观锁定选项,但是乐观锁定通常是处理并发操作的最佳方法,因为它对并发争用和性能的影响最小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM