web-dev-qa-db-ja.com

並列要求、異なる応答時間、トランザクションの原子性を処理する方法

データのテーブルがあり、行を作成、更新、削除できます。これらの操作を行うAPIがあります。次の手順が発生します

  1. 行を作成し、作成リクエストをサーバーに送信します。
  2. 行のいくつかの値を更新し、作成の応答が来る前に更新リクエストを送信します。
  3. サーバーでは、行の作成が完了していないため、更新を続行できません。

この状況にどう対処しますか?作成が成功した後でのみ更新リクエストを行う必要がありますか?サーバーにリクエストをキューイングする必要がありますか?

作成が失敗した場合、クライアントで行を削除する必要がありますか?またはリクエストを再試行する必要がありますか?これに対処する方法について助けが必要です。ありがとう

1

最も単純な解決策は、更新を送信する前に作成が返されるのを待ってクライアント側で操作をシーケンスするか、サーバー側でそれらをシーケンスできるように両方の操作を単一のコマンドで送信することです。

要件についてあまり私たちに話していないため、具体的なアプローチを推奨することは困難です。つまり、更新を送信する前に作成応答を待つと、満たされないパフォーマンス要件がありますか?

作成が失敗した場合、クライアントで行を削除する必要がありますか?またはリクエストを再試行する必要がありますか?

これも、要件と失敗の理由によって異なります。失敗の原因がネットワークのタイムアウトである場合は再試行しても意味がありますが、無効なデータが原因の場合は再試行しても意味がありません...

2
Sean Burton

非同期アプローチ

従来、データベースに行を作成するなどの非同期タスクを実行するAPIは、成功または失敗を伝える手段を提供する必要があります。これは、次の2つの方法で実行できます。

  • コールバック経由-成功または失敗時に呼び出すことができるインターフェースのインスタンスを意味します
  • Promiseを介して-これは、値が必要なときにブロックする呼び出し時にすぐに返される値です(プロセスは、値が必要になるまで並行して実行されます)。

呼び出し元は、それに応じてpromiseまたはcallbackを処理できます。複数の呼び出しが必要になる可能性がある場合は、次の呼び出しを行う前に、呼び出しが終了していることを保証する必要があります。

キューアプローチ

このアプローチは、バックエンドにより多くの責任を与えることを意味します。呼び出し元は、タスクが終了したかどうかを気にしなくなりました。あなたのAPIはそうします。つまり、タスクは呼び出し順に実行されることを保証する必要があります。これは、リクエストをキューに追加することで簡単に行えます。最初のエントリは最初に処理され、前の各タスクが終了したときに1回だけ処理されます。

取引

両方の場合、複数のスレッドが同じレコードにアクセスする可能性に備える必要があります。言い換えると、プロセスAが行1を削除して再挿入の準備をし、プロセスBがその後すぐに行1を更新しようとする可能性があります。このタイプの問題は通常、トランザクションを使用して処理されます。つまり、一連のアクションが1つのトランザクションに収集されます。 APIは、すべてが実行されるか、どれも実行されないことを保証する必要があります。

これは、トランザクション自体を注文することで実行できます。特定のトランザクションの下でAPIを呼び出すたびに、そのトランザクションは1オペレーションずつ増加します。そのトランザクションをコミットする順序が与えられるまで何も行われません。トランザクションの適切な実行順序は、そのトランザクションの作成に基づいています。これは、将来のトランザクションの影響が現在のトランザクションから見えないようにするためです。

各操作を元に戻す手段を使用して、1つのトランザクションのすべてのアクションを実行できる必要があります。途中で障害が発生した場合は、その時点までに成功したすべてのプロセスを元に戻す必要があります。トランザクションが成功した場合、変更の影響がデータベースに表示される必要があります。シングルスレッドを使用してこれらの変更を適用する場合、トランザクションの順序によって変更が保証されるため、変更を表示する必要はありません。ただし、これに複数のスレッドを使用する場合は、実行中のトランザクションの影響を、他のトランザクションが最後まで確認できないようにする必要があります。

結論

これはデータベースの仕組みやデータ変更要求の実行方法とそれほど変わらないので、この主題についての本が書かれています。これは対象を軽く軽視しますが、うまくいけば十分に作業できます。

1
Neil

何だと思う ?データベースは、ジャーナルを使用して、複数のソースからの変更を順次メモします。

UIからの変更がリクエストをエンキューできる(作成、更新、削除)ローカルにそのような構成を1つ持つことができます。別のワーカーがこのジャーナルを使用して、各要求をサーバーと同じ順序で処理できます。このキューが空の場合、すべての変更が保存されます。

リモートリソースを変更するコマンドのストリームを想像してください。各コマンドは、リモートリソースとそのネストされたフィールドを正確に特定し、新しい値を追加するか削除するかを伝えて、次のように伝えます。

+ tables/001/ [0.name] = "joe"
- tables/003/ [2]
- tables/001/ [3.age]
+ tables/002/ [0.age]  = 23
+ cars/009    [model]  = "chevy" 

編集中のリソースへの双方向ソケット接続を使用して、そのような変更を送受信できます。

0
S.D.