【问题标题】:Strategy to handle race conditions with regrads to web applicaiton backend?处理与 Web 应用程序后端有关的竞争条件的策略?
【发布时间】:2014-10-03 16:48:42
【问题描述】:

在采访中,我经常被问到有关电影票或旅游网站等网络应用程序中的比赛条件的问题。

问题是这样的。

比如巴士或机票网站,只剩下座位了。不同计算机上的两个(或在极端情况下为多个)用户同时登录网站,看到只剩下一个座位。他们都继续,选择那个座位并下订单。

现在我们必须处理两个请求。对于第一个请求,我们将预订机票,但对于第二个请求,我们必须抛出一个错误并向最终用户显示错误消息,说座位不可用。 假设数据库架构是这样的:

bus_id, seat_id,is_taken

所以对于第一个请求,我们为相应的bus_id,seat_id 1设置is_taken。然后对于第二个请求,将没有任何is_taken = 0的seat_id,因此我们不会预订机票。

但是在这里,在我看来,我们设置了一个限制,即一次只能处理一个请求;只有在第一个请求完成后,才能处理第二个请求。

但这不切实际,因为我们可能有一个巨大的网站,其中有大量的流量和应用程序在多个服务器上并行运行。我们必须并行处理请求。

由于我在处理这类多线程 Web 应用程序中的竞争条件方面没有太多经验,所以我不太清楚解决这个问题的正确方法是什么。

解决这些场景的正确(即使是基本)方法/设计模式是什么?

【问题讨论】:

    标签: multithreading web-applications backend race-condition


    【解决方案1】:

    Web 应用程序必须是多线程的。有两种方法可以解决这个问题。

    1. 应用程序级别(非首选) 我不确定您使用哪种编程语言来构建应用程序。但是所有用于构建网站的编程语言都会有类似“synchornize”的东西,它允许你防止两个线程同时访问同一个代码块。 这不是首选,因为此解决方案不可水平扩展。当您决定通过再运行一个 Web 应用程序实例来增加容量时,这个解决方案会非常失败。

    2. 数据库级别 这是首选的解决方案。您在更新之前获得数据库中记录的锁定。 SQL 提供了选择记录进行更新的选项。

      SELECT * FROM BUS_SEATS WHERE BUS_ID = 1 FOR UPDATE;

      上面的sql是获取锁的一种方式。所有的数据库都提供这种功能。使用此功能,您可以锁定所需的行并进行更新并确保数据库的一致性。

    【讨论】:

      【解决方案2】:

      在某些时候,必须有某种同步。 由于您使用的是数据库,这通常是瓶颈,您不妨让它处理竞争条件。

      您所要做的就是自动更新行。这些请求仍然可以由应用程序并行处理。

      Sql-伪代码:

      DECLARE @success = false;
      
      UPDATE bus_seats
      SET is_taken = 1, success = true
      WHERE seat_id = @seat_id AND is_taken=0
      
      return @success;
      

      【讨论】:

      • 感谢您的回答。您能否解释一下“以原子方式更新行”是什么意思?
      • @Dude 基本上,以线程安全的方式更新行。我的伪代码显示了一种方法来 1) 检查座位是否已被占用 2) 如果 它还没有被占用 3) 返回操作是否成功。确保操作是原子操作的另一种方法是使用锁,就像 Abhijith 建议的那样,但我认为您无需使用锁就可以逃脱。
      猜你喜欢
      • 2011-02-04
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多