【问题标题】:People booking for an event, How do I properly restrict the maximum number of bookings? (concurrency)预订活动的人,我如何正确限制最大预订数量? (并发)
【发布时间】:2014-03-04 01:00:09
【问题描述】:

我想这是一个经典的并发问题。

我有人报名参加活动。该事件可以处理最大数量的参与者。

这是一个带有 PostgreSQL 数据库的 Symfony 应用程序。

确保活动不会超额预订的最佳方法是什么?

假设我有名为 Event、Person 和 Booking 的实体。 Booking 与 Person 和 Event 有一对多的关系。

我显示有关该事件的页面。我计算当前预订,如果数量小于最大值,则显示“立即预订”按钮。

这是我以前如何完成此操作的一些伪代码:

关于立即预订按钮的操作:

Count bookings
if count >= max
  return "Sorry, this event is full"
else
  Create booking
  Flush entity manager

  Count bookings again

  if count > max
     Delete booking
     return "Sorry, this event is full"
  endif

结束

我认为这种方法是安全的,但并不理想。我认为这可能会导致两个人预订时,只剩下一个空间并且两个人都被拒绝了。现实世界中发生这种情况的可能性可能接近于零,我猜用户会再试一次,但是……如果能正确地做到这一点,那就太好了。

有没有更好的方法来做到这一点?

我读过这篇文章:Handling the concurrent request while persisting in oracle database? 和几个月前我问过的一个类似问题。当最大预订量 = 1(例如航空公司座位)时,乐观锁定似乎是一个好策略。在那种情况下,我可能根本就没有 Booking 实体。事件是否只有一个人。

【问题讨论】:

    标签: postgresql symfony concurrency


    【解决方案1】:

    查看教义文档Concurrency and Transactions,您可以使用一些选项。

    我同意乐观锁定可能是要走的路,但您不必更改当前的逻辑。只需向要插入的实体添加一个新的version 字段(最好键入serial),然后在执行初始选择时,传入唯一的版本号。那么当你插入的时候,如果版本变了,你就知道别人已经预订了,插入就不会发生了。

    文档中有一些关于Optimistic Locking 的好例子

    更新

    乐观锁定将在更新实体时起作用。对于插入新实体,交易将是最好的选择。

    【讨论】:

    • 谢谢。我想我理解乐观锁定,但我不明白在向表中添加新行时它是如何应用的,这就是我预订时发生的情况。更新现有行时,乐观锁定似乎很有用。如果自您上次阅读后版本已更改,则您知道其他人已对其进行了更新。我没有看到如何使用它来限制我可以在我的 Booking 表中具有特定 event_id 值的行数。这似乎是一个不同的问题。
    • 事务可能是要走的路,但我认为我需要关注隔离级别。即,我可以在计数时看到其他用户的预订吗?我什至可以在 Symfony / Doctrine 中控制它吗?我想知道其他人在 Symfony 中是如何做到这一点的。
    • 你是对的,我误解了这个问题。乐观锁定用于更新实体。我不太明白你的意思 - can I see other users' bookings when I count?
    • 我对事务和隔离级别的理解还不够好,但不知何故我需要问“这个活动是否已订满?”。最明显的方法是 SELECT COUNT(*) FROM Booking WHERE event_id = ?计算预订。如果它小于最大值,那么我会继续 INSERT INTO Booking,但我需要防止其他人做同样的事情,我猜这意味着我需要在提交之前再做一次 SELECT COUNT(*)。我认为隔离级别会影响我是否会看到其他未提交的预订。也许我想多了,有更好的方法。
    • 阅读本文第 13.2.3 节:Postgresql Isolation levels,它可能会帮助您了解可能的情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多