web-dev-qa-db-ja.com

映画館の座席予約システムでは、複数のユーザーが同じ席を予約するのをどのように防ぐのですか?

映画館では、行きたい座席を選択できるチケットキオスクを持っています。彼らはまた同じことをするウェブサイトを持っています(ウェブサイトはまたあなたが座席を選ばなければならない30秒のようなカウントダウンタイマーを持っています)。

データベーストランザクションや複数の同時ユーザーを処理するためのその他の手法などについては理解していますが、同時に複数のユーザーが座席を選択できるようにする方法について頭を悩ませることはできません。最初に[購入]を押すのと同じくらい簡単ですが、他の人にエラーメッセージが表示されますか、それとも何か不足していますか?

34
mbwasi

これを行うための古典的な方法は、トランザクションデータベースを使用して(衝突がないため)、一定期間(たとえば、キオスクの場合は10分)後に有効期限が切れる暫定的な割り当てを行うことです。 )それはあなたに支払うのに十分な時間を与えます。 (顧客に表示される)トランザクションが失敗するかタイムアウトした場合、シート割り当てを解放してプールに戻すことができます。 (すべての状態変化はトランザクションデータベースを介して処理され、1つの顧客に見えるトランザクションは多くのデータベースレベルのトランザクションを必要とする場合があります。)

航空会社は、オンラインで座席を予約するために同様のシステムを使用します(ただし、複数のフライトレッグを処理する必要があるため、はるかに複雑です)。タイムアウトはかなり長くなると思います。航空券は通常、映画のチケットよりも先に予約され、同様に高価です。

28
Donal Fellows

あなたが見た30秒は、今日ではしばしば15分に近いです。その間アクティブなデータベーストランザクションがあるとは思いません。

そのようなシステムを設計する場合、これは私がそれを行う方法です。ビジネスオブジェクトBookingReservationを用意します。予約は基本的に確認済み(つまり、支払い済み)の予約です。それらを同じDBテーブルに格納し、1つまたは2つの属性で区別します。

利用可能な座席を取得する場合、予約と予約の両方をクエリします。

誰かが座席を選択すると、新しい予約が作成され、他の顧客に空席が表示されます。同じシートの2番目の予約は拒否されます-DBの更新または挿入は失敗します。お客様が予約を確認/支払うと、予約に移行します。定期的なバッチジョブでは、15分(または顧客に提供する時間)より古い予約をすべて削除します。

4

特定の座席の割り当てを遅らせると、競合状態を回避できます。

  1. お客様から座席の好みを収集します(座席数、価格、劇場の面積、隣接する座席が必須など...)
  2. リクエストされた座席設定をキューに保存する
  3. 1つずつの座席リクエストがキューからプルされ、優先順位に従って座席が割り当てられ、座席が見つかった場合は予約が完了します。
  4. 予約が完了したら、顧客に通知してチケットを郵送します。それ以外の場合は、優先と一致するチケットがないことをお客様に通知します。
1
Ed James

ここには少なくとも2つのビジネスプロセスが関係しています。

  • プロセス1:

利用可能な座席を表示します。

  • プロセス2:

選択した座席を予約します。

これらのプロセスは互いに過度に追従しないため、また2人が同じ座席を選択する可能性があるため、同時実行の問題が発生します。

データベース設計が正しい一意性制約を割り当て、次の組み合わせになる場合:

-TheaterID

-SeatID

-EventID

一意である場合、データベースは重複を防止します。

次のシナリオも可能ですが、上記の提案された実装によって処理されます。

特定の劇場と特定のイベントで利用可能なグリッドビューを表示できると仮定します。

  1. User1は利用可能な座席を表示します(そして、座席1と2を取得します)
  2. User2は利用可能な座席を表示します(そして、座席1と2を取得します)
  3. User1は顧客と電話で少し話します
  4. User2が行き、顧客のために座席2を予約します
  5. User1は顧客のために座席2を予約しようとします(画面に空席があると表示されているため)
  6. 一意のインデックスは、ステップ5がデータを交換することを防ぎます。

したがって、必要なことは、データベースを正しく設計し、制約を適切に選択することだけではありません。

必要に応じて、トランザクションキューを使用する他のより複雑なアプローチが可能です。この場合、リクエストは最初にキューに書き込まれ、次にn秒ごとにプロセスを起動しますが、それはあなたのケースではほとんど必要または実用的ではありません。

本当に興味深い部分は、ユーザー1のリストグリッドが何を表示する必要があるかです。

1
NoChance

これは、データベースのACIDプロパティ-分離と連動します。データベースは、データのロックを使用して、データの同時変更を回避します。

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

1
user841923