2

Azureテーブルストレージにテーブルがあるとしましょう

public class MyTable
{
  public string PK {get; set;}
  public string RowPK {get; set;}

  public double Amount {get; set;}
}

そして、AzureQueueに「Add10toAmount」というメッセージが表示されます

ここで、1人の労働者の役割を考えてみましょう

  1. このメッセージをキューから取得します
  2. テーブルから行を取得します
  3. 金額+=10
  4. テーブルの行を更新します
  5. そして失敗する

しばらくすると、メッセージが再びキューに入れられます。したがって、次の労働者の役割:

  1. このメッセージをキューから取得します
  2. テーブルから行を取得します
  3. 金額+=10
  4. テーブルの行を更新します
  5. キューからメッセージを削除します

これらのアクションは、のAmount += 20代わりになりAmount += 10ます。

どうすればそのような状況を回避できますか?

4

4 に答える 4

2

一種の楽観的並行性を実装することをお勧めします。行を更新するために送信するメッセージには、amount プロパティの「前の値」と「新しい値」の両方が含まれている必要があります。

そのため、行を更新しようとする 2 番目の worker ロールは、最初に現在の値がまだ "前の値" と等しいことを確認します。そうでない場合、worker ロールは何かがうまくいかなかったことを認識しており、たとえば、更新を行わずにメッセージをキャンセルすることができます。また、おそらくログにもエラーが発生します。

于 2009-12-11T12:38:28.347 に答える
1

キューに入れるすべてのメッセージはべき等でなければなりません。ワーカー ロールがジョブを完了できない可能性は常にあるため、メッセージは繰り返し可能でなければなりません。

したがって、タスクとして amount += 10 の代わりに amount = 300 のようなことを行います。webrole で現在の金額を取得し、それに 10 を追加して、新しい金額をキューに入れます。

これが正しい方法かどうかはわかりません。このようにすると、2 つの webrole が同時に 10 を追加しようとすると問題が発生します。

于 2009-11-24T15:35:51.957 に答える
0
  1. キュー内のメッセージに固有の MessageId を用意します。
  2. Worker ロールはキューからメッセージを読み取り、テーブルからエンティティを読み取ります
  3. 金額フィールドを更新します
  4. バッチ操作を行い、2 行をテーブルに挿入します。1 つ目はテーブルにマージされた更新済みエンティティで、2 つ目は行キーと同じパーティション キーとメッセージ ID で挿入されたエンティティです。

バッチ操作はアトミックに実行されます。

  1. この例では、別のワーカー ロールが同じメッセージを 2 回目に処理しようとすると、メッセージ Id がテーブルに既に存在するため、その操作は失敗します。Worker ロールは、ストレージ例外からそのステータス コードをキャッチし、キューからメッセージを削除する必要があります。

これは完全に冪等であり、必要なだけワーカー ロールをスケールアウトできます。さらに、FIFO を保証しないキュー内のメッセージの順序に依存しません。

于 2016-02-07T02:08:04.243 に答える
0

あなたはこれを実装しましたか、それともそこにあるコード行はほんの少しの考えですか?

「金額」は、ある種の銀行取引シナリオを考えていることを意味します。おそらく、SQL Azure を直接操作する方がよいでしょう (ACID 保証があるため : http://blogs.msdn.com/ssds/archive/2009/03/12/9471765.aspxこのサービスは引き続き提供されます。」)

Windows azure の「テーブル」は、Google の bigtable のようなものだと言えますね。

于 2010-04-09T17:40:56.540 に答える