RESTは楽観的同時実行制御のみに制限されていますか?


9

環境

RESTアーキテクチャスタイルのステートレス性により、各リクエストは完全に独立しており、サーバーはクライアントに関する情報を決して保存しません。

したがって、どのクライアントがリソースのロックを取得するかをサーバーストアに要求するため、悲観的な同時実行制御は適していません。次に、Etagヘッダーを使用して、オプティミスティック並行性制御が使用されます。(ところで、私がそこに尋ねたように/programming/30080634/concurrency-in-a-rest-api

問題

楽観的同時実行制御メカニズムの主な問題は、すべてのクライアントがいつでも任意の操作を実行できるようにすることです。

そして、RESTの無国籍原則を破ることなく、それを回避したいと思います。つまり、すべてのクライアントがいつでも操作を実行することはできません。

質問

私の考えでは、次のような準楽観的同時実行制御メカニズムで可能です。

  • クライアントはトークンを要求できます
  • 生成できるトークンは1つだけで、有効期間は限られています
  • リソース(POSTPUTなど)で操作を実行するには、クライアントはこのトークンをリクエストの本文(またはヘッダー?)の一部として渡す必要があります。トークンを持たないクライアントは、これらの操作を実行できません。

これは、楽観的同時実行制御に非常に似ていますが、「すべてのクライアントがすべての操作を実行できる」とは逆に、1つのクライアントのみが一部の操作(トークンを取得したクライアント)を実行できる点が異なります。

このメカニズムはRESTアーキテクチャスタイルと互換性がありますか?それはその制約のいずれかを破りますか?私はSOについて質問することを考えていましたが、これはソフトウェア設計に関連する、よりハイレベルな質問のようです。


1
それは実際にはかなり単純ですTransaction。明示的にリソースとしてモデル化する必要があります。
イェルクWミッターク

何が変わりますか?コメントが理解できません。私はトランザクションの同時実行制御を行っていませんが、クライアントに「わかりました。リソースが変更されることは絶対にありません」(一意のトークンを取得しているため)と言っています。
AilurusFulgens 2015年

1
違いはなんですか?一方では、Etagを使用して、「現在の」バージョンを更新できるユーザーを確認します。衝突する場合は、バージョンを更新してから更新する必要があります。一方、「ロック」メカニズムがあります。1つは許可され、もう1つは待機する必要があります。かなり同じように聞こえます。2番目のアプローチの欠点:2つの要求-1つはロック、もう1つは更新。最適なケースでは、Etagアプローチによる更新は1つだけです。
トーマスジャンク

まあ、一般的に同時実行制御について言えば...「レースに負けた」2番目は常に待たなければなりません(さまざまな理由で、私はそれに同意します)。との違いはEtag?ではEtag、あなたの操作が完全になることを確認してくださいことはありません、あなたが任意の操作を実行することはありません決して状況を持っている可能性があります。ロックがあれば、少なくとも操作は確実に行えます。したがって、単純なロックを持つことは、「高い競合」と「まれな競合」が発生する可能性がある環境のちょうど中間です。
AilurusFulgens 2015年

回答:


3

ユーザーインタラクションを待機している間は、リソースを決してロックしないでください(決してこれまでにないように)。

ある時点で、一部のユーザーは長期週末に離陸し、いくつかの重要なレコードをロックしたままにします。

ああ、でも、巧妙なタイムアウト/デッドロックの解決方法があるので、それを起こさせません。その後、ある時点でこれはひどく間違ってしまい、「あなたのウィジェットが注文されました」という素敵なメッセージを受け取ったユーザーがヘルプデスクで叫び、自分のウィジェットが配信されなかった理由を尋ねます。

ほとんどの人は、「別のユーザーがこの部品を注文したばかりです」というメッセージに対処できます。


あなたはそれをうまく説明しました。私はあなたの最初の文に完全に納得していませんが、ある時点で、注文を実行できるのはあなた以外の誰もいないことを保証します。しかし、まあ、あなたの最後の文は、99%の場合において、良い要約です。
AilurusFulgens 2015

1
特定のユーザーのレコードをロックする必要がある場合は、アプリケーションレベルでロックします。単純な「LockedBy」属性、またはより洗練されたバージョン管理とワークフローメカニズムを使用します。
James Anderson

「アプリケーションレベル」とはどういう意味ですか?リソースに「LockedBy」属性を追加すると、クライアントに関する情報がサーバーに格納されます。または、コメントが理解できなかったのかもしれません。いくつかの詳細を提供することができればそれは素晴らしいでしょう!
AilurusFulgens 2015

1
@AilurusFulgens-データベースにLockedBy属性(および場合によってはLockedOnタイムスタンプ)を追加します。アプリケーションコードでは、クライアントが更新操作を開始するたびにユーザー名と時間を設定します。クライアントが終了すると、あなたはそれを設定解除-あなたがして解決の競合やタイムアウトなどにいくつかのビジネスルール外の仕事に必要
ジェームズ・アンダーソンは、

2

トークンの使用はAPIで非常に一般的です。これらのトークンは通常ヘッダーとして送信され、明確なライフサイクルがあります。たとえば、OAuthについて考えてみましょう。

プログラミング言語やフレームワークに関係なく、REST APIは似ています。

並行性を制限したいシナリオがいくつか考えられますが、そのうちの2つは次のとおりです。

  1. 複数のクライアントがデータベース行のように同じリソースを更新します。たとえば、2つの同時要求、1つはレコードを削除し、もう1つは同じレコードを更新しようとします。データベースとその設定方法によっては、データが異なるか存在しないため、レコードがロックされるか、無効な操作が行われる可能性があります。

  2. APIで特別なアクションを実行するスーパーユーザーまたは管理者。


これらの場合はどうしますか?

  1. データベースのトランザクション、シングルトン、ロック、および同様のメカニズムを使用して、リソースへのアクセスを同期します。

  2. トークンは機能するかもしれませんが、クライアント自体に関する情報だけを保存しない方が良いと思います。1つのステップでユーザーを検証し、トークンを割り当てることができます。次に、トークンが有効で有効であることを確認します。復号化できるトークンを使用して、追加情報を取得します。これが特別なトークンである場合は保存して、一度にのみ許可できます。この方法では、ユーザーではなくトークンを検証します。

これがお役に立てば幸いです。


はい、私はトークンとOAuthメカニズムの類似性についての応答を期待していました。最後のものは認証専用ですが。シナリオの要点を理解できませんでした。1。REST APIで同時実行性を処理する際に注意が必要なのは、ステートレスの制約を維持することです...つまり、サーバーはクライアントに関する情報を保存しません。シナリオ2はまさに私が現在行っていることです!:)
AilurusFulgens 2015

私はあなたの質問に答えましたか?
パブログラナドス2015

申し訳ありません。私はあなたの答えに賛成しました。問題の概要がよくわかるからです。
AilurusFulgens 2015

0

RESTだけでは、あまりにも原始的です。RESTを使い始めることもできますが、最終的には、リッチアプリケーションで結合を使用したクエリとトランザクションを使用した更新が必要になります。これらを独自に追加しようとするすべての開発者は、エラーが発生しやすく、一貫性がありません。幸いなことに、それを行うODataと呼ばれる新しい標準があります。RESTの上に階層化され、(1)(外部キーを公開する必要なしに)ナビゲーションプロパティを使用して単純な結合を可能にするクエリ言語、および(2)アトミック変更セットを含むバッチ処理を提供します。

(1)についてはこちらを参照してくださいhttps://stackoverflow.com/a/3921423/471129、および、

ここと(2)を参照してくださいhttps://stackoverflow.com/a/21939972/471129

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.