正しく結果を出すために2つのデータ入力を必要とする負荷分散サービスがあります。
これらの入力の1つはキューからのもので、もう1つはユーザー入力からのものです。
ほとんどの場合、キューからのデータは、ユーザー入力のかなり前に到着します。キューからのこのデータはデータベースに保存され、ユーザー入力が到着すると、結果を作成するために使用されます。
しかし、ユーザー入力が最初に発生する時間の約10%。その場合、ユーザーに応答を返す前にキューデータが到着するのを待つ(つまり、プロセスをブロックする)必要があります。
10%シナリオの問題は、キューデータがいつ到着したかを知っているため、続行できます。 「あなたはいますか?」、「今ここにいますか?」、「今はどうですか?」しかし、私は多くの理由でそれが好きではありません。
(通信を処理するためにプロセスを使用することも検討しましたが、サービスが負荷分散されているため、機能しません。)
他のアプリケーションがこの種のことを処理する方法はありますか?データが存在するまで何度も何度もデータベースにpingを実行する必要がないものですか?
結果をリクエストの結果としてではなく、イベントのフォローアップとして見てください。質問はあまり具体的ではないので、抽象的な言葉でしか話せません。以下が最善のアプローチだと思います。
タスク、ユーザーからの入力:
タスク、キューからの入力:
このアプローチでは、負の側面は責任の重複です。それがトレードオフです。実装は、「結果の作成」の性質とコストに依存します。主な利点は、このアプローチの方が、メッセージを待機したり、リクエストを頻繁に送信したりするプロセスを維持するよりも安価でシンプルなことです。この答えは詳細によっては関係ないかもしれませんが、件名がプロセス、メッセージ、関数、ファイル、イベントなどであるかどうかにかかわらず、哲学は有効であると思います。
これに取り組み、競合状態の可能性を回避する1つの方法は、次のようなテーブル構造を作成することです。
----------------------
| ID | user | queue |
----------------------
| 12 | N | N |
----------------------
どちらかが入る前にこのIDを知っている場合は、そのときに行を作成できます。次に、ユーザーハンドラとキューハンドラの両方で、select for update
をクリックし、それぞれの列を更新します。同時に、他の列を確認します。 tが設定されている場合、両方が使用可能であり、続行できることがわかります。どちらの方法でも、トランザクションを更新してコミットします。
または、最初に、IDとそれぞれの列を 'Y'(または使用したいもの)に設定して行を挿入しようとし、失敗した場合は更新を追跡できます。理想的な世界では、挿入の失敗は反対側が完了したことを示すので、更新を追跡する必要はありません。ただし、何かがうまくいかず、片方がこれを2回行うと、問題が発生します。両方の列が設定されていることを確認すると、準備ができていると確信できます。これにより、2つ以上の入力にアプローチを使用することもできます。
クライアントのブロッキングを処理するために、別のキューを使用できます。クライアント要求が届くと、更新ロジックを起動し、キューで応答を待ちます。次に、上記のロジックは、両方の入力が解決されたときにメッセージをキューに送信します。
これを行うには、負荷分散されたサービスのインスタンスごとに「入力キュー」を作成します。入力(ユーザーまたは私の質問で "キュー"とラベル付けされたもの)を受け取り、キューに入れます。私は両方の入力にあるキー値をハッシュし、そのハッシュを使用して入力が入るキューを選択するつもりです。これにより、1つのキュー(および1つのサービスインスタンス)が両方の入力を取得し、それらが同期的に発生することが保証されます。
確認できたら、両方のメッセージが表示されるまで待機してから、サービスの操作を実行できます(Lacyと同様)。 (競合状態の問題から安全です。)