【问题标题】:How to handle this concurrency scenario with NHibernate + asp.net mvc?如何使用 NHibernate + asp.net mvc 处理这种并发场景?
【发布时间】:2017-05-03 02:34:12
【问题描述】:

上下文:用 asp.net MVC + NHibernate 编写的 Web 应用程序。这是一个纸牌游戏,玩家同时进行游戏,因此他们的动作可能会同时修改实体的同一字段(他们都在一个字段上执行 x = x + 1)。看起来很经典,但我不知道如何处理。

不用说,我不能向用户显示“实体已被其他玩家修改。合并或取消?”的弹出窗口。当你认为这与卡牌的动作有关时,我不能这样干涉。我的应用程序必须在内部处理这种情况。由于该字段位于实体类中,并且每个会话都有自己的实体实例,因此我不能简单地使用 CLR 锁。这是否意味着我应该使用悲观并发,以便在该实体上执行的每个 Web 请求都排队,直到玩家完成他的操作?实际上意味着每个 PlayCard 请求都应该使用一个锁?

请不要将我发送给关于并发或类似的 NH 文档。我关注的是在这种情况下应该使用的技术,而不是如何在 NH 中实现它。

谢谢

【问题讨论】:

  • 听起来您想要一个系统,其中多个用户都能够修改实体属性(在服务器上),没有任何并发​​问题 - 即没有锁,但所有更新都成功?这当然是不可能的 - 只有两种可能性 - 要么您锁定并允许一次只进行 1 次更新,要么您允许所有更新成功,但接受最后一次更新将覆盖任何较早的更新。跨度>
  • 我的直觉是我必须锁定,不仅是更新,还有“选择+更新”序列。否则我的 x = x + 1 示例将不起作用。我不能接受并发更新,因为初始 x = 1,在所有玩家行动后 x 将是 2 而不是 3。所以我的问题更像是“我说得对吗,比如说 PlayCard 动作,所有的网络请求都应该被会话锁定”?
  • 我不会在这里使用数据库。我会让客户端 ajax 调用服务器 - 这将允许更新或阻止它,具体取决于哪个首先进入那里 - 将原始值与当前值进行比较。在服务器端,我会将实体保存在单例中以提高响应速度。
  • 谢谢,但不可能。 x+1 只是一个例子,我有很多不能放在客户端的逻辑,只能放在服务器端。
  • 谁说客户端?我只是说使用 ajax 来提高速度 - 逻辑仍然是服务器端。

标签: asp.net-mvc nhibernate concurrency


【解决方案1】:

根据您的业务逻辑,尝试二级缓存可能有意义。这可能是一个很好的取决于游戏的长度和它是如何玩的。由于二级缓存存在于会话工厂级别,因此必须根据游戏的生命周期来管理会话工厂。可以为每个请求创建 Nh 会话,但由配置为二级缓存的会话工厂生成意味着感兴趣的数据将在所有会话中缓存。使用二级缓存的优点是您可以逐个类地配置它 - 只缓存您需要的实体。它还根据缓存提供者提供了多种并发策略。尽管这可能会将并发问题从 DB 级别转移到 NH 会话,但这可能会为您提供更好的选择来处理您的情况。使用它有一些问题,但它的适用性完全取决于您的业务逻辑。

【讨论】:

【解决方案2】:

您可以尝试以这种方式应用乐观锁定:

DB 实体将具有列跟踪实体版本 (nhibernate.info link)。

如果您在保存实体时遇到“旧版本”异常(= 被其他用户修改) - 重新加载实体并重试。然后将更新后的值发送给客户端。

据我了解,您的后端收到来自客户端的请求,然后打开会话,进行一些更改并更新实体关闭会话。在这种情况下,没有线程会将一个实体在内存中保存太长时间,并且乐观锁定冲突不应该经常发生。

这样可以避免很多锁定线程等待操作完成。

另一方面,如果您希望重试过于频繁,您可以在加载实体时尝试 SELECT FOR UPDATE 锁定(在 NH Get 方法中使用 LockMode.Upgrade)。虽然我发现了阻止我在 SQL Server 中使用它的线程:SO link

一般来说,解决方案取决于游戏的逻辑以及您是否可以在不向用户显示消息的情况下解决代码中的并发冲突。我还让 UI 经常使用最新数据进行自我更新,以避免玩家在过时的游戏情况下采取行动,然后对结果感到惊讶。

【讨论】:

  • 谢谢。然而,这在我的 mvc 应用程序的上下文中是困难的,其中会话在请求开始时自动创建并在远端关闭。获得一个陈旧的实体意味着会话是无用的,因此我必须手动重新打开一个会话,这会破坏我现有的工作单元。但无论如何我理解你的逻辑。
  • 嗯,您是否可以将此更改包装在一个较小的事务中并尝试立即提交?如果失败则重试。您可以同时保持会话打开。不确定工作单​​元在您的情况下有多重要。
  • 这是否意味着必须将实体重新附加到子会话?实体有很多孩子没有问题吗?
猜你喜欢
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 2012-03-30
  • 2014-05-07
相关资源
最近更新 更多