次の設定があります。デプロイされた Azure ワーカー ロールの N インスタンスがあります。デスクトップ アプリケーションがメッセージを Azure にアップロードすると、メッセージに関連する一連の画像がアップロードされます。メッセージは、必要な画像を認識しています。
これら 2 つのアクティビティ (メッセージのアップロードと画像のアップロード) は独立しています。画像は、メッセージがユーザーによって生成される前 (キャッシュと呼びますが、より複雑です)、またはメッセージが Azure にアップロードされてから数秒または数分後にアップロードできます。
メッセージは Azure MSSQL データベースに保存し、画像は BLOB に保存し、それらへの URL はデータベースに保存します。また、メッセージの画像へのリンクを格納するMessageToImageテーブルもあります。これは単純化されたDB構造です(私のC#を許してください):
class Message
{
public int Id;
public string Text;
}
class Image
{
public int Id;
public string Name;
public string BlobUrl; // Null if image was not received by the service yet
}
class MessageToImage
{
public int MessageId;
public List<int> ImageIds;
}
そして、すべての画像の準備が整った (つまり、すべての画像がアップロードされた) メッセージを受け取ったら、それを使って別のことをする必要があります (たとえば、Facebook に投稿します)。ここに質問があります:メッセージが 1 回だけ処理されることを保証するにはどうすればよいですか? 最悪のシナリオでは、メッセージの N 個のイメージを同時に受信する N 個のインスタンスがあり、どのインスタンスがその後の処理にメッセージを送信する必要があるかを「選択」しますか? そして、それが一度だけ起こることをどのように保証できますか?
これまでのところ、次のアイデアを思いつきました。
「画像の BlobUrl を更新する」データベース ロジックがアトミックであり、メッセージに対して「不足している」画像の数が返されることを確認してください。このようにして、1 つのインスタンス (データベース更新の結果として "0" を受け取るインスタンス) でのみ、さらなる処理をトリガーします。しかし: MSSQL レベルでどうすればそれを行うことができますか? さらに複雑 - Entity Framework を使用してそれを行うにはどうすればよいですか?
すべての画像を含むメッセージを選択する専用のワーカー ロールを用意し、それらを処理のために送信します。しかし、それはうまくスケーリングできません...そして少し醜く見えます。
他のアイデア/提案はありますか?
ありがとう!
UPDATE1 @Richard と @Rob は、Service Bus Queue の使用を提案しました。私はそれを調べました。私がまだ答えを持っていない部分は、処理のためにメッセージをキューに送信するタイミングを決定する WORKER ROLE のコードがどのように見えるかです。すべての画像がデータベース/BLOB に存在する (つまり、Azure クラウドにアップロードされた) 場合にのみ、メッセージがキューに送信されます。ここで、コーナー ケースの例を挙げたいと思います。10 個の画像が 10 個のワーカー ロールによって同時に処理されています。すべてのインスタンスの処理が同時に終了します。各ロールは、アップロードされた画像 URL でデータベースを更新します。そして、どうにかして最終的なメッセージ処理をトリガーする必要があります。つまり、インスタンスの 1 つが優先される必要があります。そして、私はこれをどのように行うべきか明確ではありません。
これにより、私の質問が少しきれいになることを願っています。