Windows Azure によるスケーラブルなカウンター ~ クラウド カバー Episode 43
みなさん、こんにちは。
今回は、米国 Microsoft のエバンジェリスト Wade と Steve による Channel 9 のコーナー Cloud Cover の Episode 43 を紹介したいと思います。
さて、いつもの通り冒頭はニュースから。
◆ MSDN Magazine: Introducing the Windows Azure AppFabric Caching Service
Windows Azure AppFabric Cashing Service の紹介記事です。Mix 11 でも Wade が AppFabric Caching のセッションを行いますのでそちらもぜひ。
◆ New Windows Azure Code Quick Start samples are available
Windows Azure のクイックスタートサンプル。コードレベルでの解説が入っているのでわかりやすいです。日本でいう Code Recipe 的な開発者向けガイドですね。私も WCF のコードあとで試したいと思います。
◆ Japanese MVPs help out with relief efforts
東日本大震災の際に MVP、コミュニティの皆様が活躍されたことに関して取り上げています。関係者の皆様には改めて御礼申し上げます。
◆ Windows Azure helps to power eBay's iPad Marketplace sales
eBay における iPad のマーケットプレイスにおいて、Azure を採用したニュースです。eBay においては Java を用いているようですが、今後のプラットフォームのクラウド化を睨み、iPad のマーケットプライスにおいて Azure の適用を開始したようです。eBay は Azutre Appliance のパートナーでもあることから、今後の展開が期待できます。
さて、ここからが今回の本題。
冒頭、Google の +1 ボタン、Linkedin の Share ボタン、のようなソーシャルなボタンを取り上げながら、多数のユーザーが同時にストレージに対する書き込みを行うシナリオを紹介します。
今回は Azure において、「こいつはつまらない!!! 」ということを共有する Apathy Button の実装を行います。
(すでに 37,973 人の方が、つまらない!と言っています)
(1) 単純な実装パターン
今回のアプリケーションを Web Role が、更新後の数値を書き込む、という実装を行うと(たとえばユーザーの操作前に 5 だったカウンターを、操作後は6としてストレージに書き込もうとすると)、そのような書き込みが複数の Web Role から同時にリクエストされた場合に Azure ストレージでうまく扱うにはすこし複雑な実装が必要になります。Optimistic Concurency (楽観的同時制御)で排他制御を行う手もありますが、更新のスピードを超えるユーザー操作が発生した場合は、競合の解決が終了しなくなる可能性もあります(楽観制御により書き込みに失敗した Web Role (A) は再度書き込みを行おうとしますが、そのスピードより速く他の Web Role (B) が情報を更新してしまうと Web Role (A) は再び書き込みに失敗します)。
つまりこの実装では、ユーザーが増加した際にうまくいかない可能性が高そうです。
(2) Cache を利用するパターン
解決方法の一つ目として Azure ストレージへの書き込みを一つの Writer (Single Writer)に限定し、Azure ストレージにおける競合をなくす方法です。実装例としては、アトミックなインクリメンタルな操作を実行できる Cache (※)を用意する一方で、Cache の値を定期的にチェックし Azure ストレージに書き込む Writer を用意することです。
(※) 複数の Role から同時に増分の操作が行われても、正しく実行できる能力を持つ Cache。 たとえば、AppFabric の Caching Service では アトミックなインクリメンタル操作がサポートされます。
(3) 各 Web Role が専用データ領域を持つパターン
次はそれぞれの Web Role が専用のデータ領域(Azure ストレージ上での行)を保有し、そこを Update していく方法です。この場合、定期的に各 Role の更新データを見て、総数を計算するロジックが必要になります。また、各 Role においても複数スレッドが動いているため、スレッド間の調整を行う必要があります。
ということで、この方法を実装したのが、今回の Apathy Button (下図は Steve の Blog エントリより)です。
HomeController の Initialize にて、各 Web Role から Azure ストレージの専用データ領域にカウント値を書き込みを行うスレッドを一つ用意します(上記図の赤色の Update Thread の部分)。また、HomeController の CurrentCount() メソッドでは、複数の Web Role がそれぞれに書き込んでいる Coun 値から総数を計算するロジックが用意されています。
また各 Web Role において複数スレッドが安全にアトミックなインクリメンタル操作ができるように、Interlocked.Increment() メソッドが使用されます(上記図の水色の Concurrent Requests の部分)。
ということで、ソースをダウンロードしたら、VS で立ち上げて F5。これで今回のソースを試せます
なお、デフォルトでは Update Thread および、画面のリフレッシュのいずれも 5秒の更新間隔に設定されていますので若干もっさりした動作になります。きびきびっと動作させたい場合はリフレッシュの待ち時間を変更してみてください。
では、Enjoy Coding!