Web インフラストラクチャ

ASP.NET アプリケーションのスケーラビリティを確保する

Iqbal Khan

 

概要:

  • ASP.NET アプリケーションのスケーラビリティのボトルネック
  • セッション状態の記憶域のオプション
  • 利用できるキャッシュ トポロジ
  • 必要なキャッシュ分散機能

目次

問題の所在
これらの問題が存在する理由
解決策
キャッシュ トポロジ
別の選択肢
実際の使用

マイクロソフトの Web アプリケーション フレームワークである ASP.NET の人気は、依然として、開発者、企業、IT ユーザーの間で急速な高まりを見せています。ただし、ASP.NET アプリケーションには、既定の状態ではスケール アウトができないという問題があります。

この場合のスケーラビリティには、2 つの意味があります。まず、どのようなアプリケーションでも、ある時点でログインしているユーザー数の山と谷があるため、ピーク時のユーザー負荷を適切に処理できる必要があります。インフラストラクチャを設計するときは、ピーク時の負荷をピーク時以外の負荷と同程度の効率と時間で処理できるように、アプリケーションを設計する必要があります。

また、システム全体のキャパシティを拡大できる必要があります。現在は 5,000 ユーザーしかいないかもしれません。しかし、半年後、1 年後には 10,000、15,000、20,000 ユーザーとなり、数年後には 100,000 ユーザーにまで膨れ上がることも考えられます。アプリケーションを酷使して停止させることなく、ユーザー数に合わせて拡張できるというのが、スケーラビリティです。つまり、認識できるほどの悪い影響をパフォーマンスに与えることなくユーザーを追加できるか、パフォーマンスが低下しても、それが許容できる範囲内のものである必要があります。

通常、ASP.NET アプリケーションは、Web ファーム内で連携している 1 台以上の Web サーバーに展開され、Web ファームでは、すべての Web サーバーにトラフィックを分散するロード バランサが使用されます。理論上は、Web サーバーを追加すればするほど、1 秒間に処理できる要求数は多くなります。この Web ファームのアーキテクチャにより、ASP.NET アプリケーションのスケーラビリティを確保できるはずです。しかし、これはあくまでも理論であり、実情は少し異なります。

ASP.NET アプリケーションの問題は、Web テクノロジにより Web ファームとロード バランサというすばらしいアーキテクチャを実現できていても、データ記憶域テクノロジがそれに追いついていないことにあります。確かに、サーバーを追加したり、メモリや CPU 性能を上げて個々のサーバーを強化することで、Web アプリケーションをスケール アウトすることは可能です。

しかし、その場合に、データ記憶域を同じような比率で拡張することはできません。拡張はできますが、Web アプリケーション層ほどではありません。このため、ASP.NET アプリケーションで実行されるデータ記憶域やデータ アクセスに関連する操作は、スケーラビリティのボトルネックになる可能性があります。さらに問題なのは、セッション データとアプリケーション データのどちらについても、データベース サーバーを拡張できないことです。

問題の所在

ASP.NET アプリケーションで実行されるアクセスや記憶域の操作について考えてみましょう。まず、セッションの記憶域操作について説明します。どのようなユーザー要求でも、セッションは開始時に記憶域から読み取られ、応答の終了時に記憶域に書き込まれます。ユーザー要求の最初に、ページが実行される必要があります。そのため、ページではセッション データが必要になります。"セッション オブジェクト" と呼ばれるセッション データ全体が読み込まれ、実行中に、ページがこのデータを参照できるようになります。ページでは、セッション オブジェクトから、必要なデータの一部を読み取り、さらにデータをセッション オブジェクトに追加します。この操作はすべて ASP.NET プロセス内で実行されるため、セッションの記憶域へのアクセスは行われません。

ページの実行が完了した時点で、ユーザーに結果が返される必要があります。おそらく、この間に、セッションは更新されているため、セッションを記憶域に保存する必要があります。この保存されたデータは、同じセッションに対して次のユーザー要求が行われるまで保持され、要求があると同じプロセスが繰り返されます。

ユーザーの視点では、ユーザーがリンクをクリックし、その結果としてページが表示されるまでに、セッションの読み取りと記憶域への書き込みが 1 回ずつ実行されています。したがって、ASP.NET アプリケーションでは、セッションの記憶域に対して 2 回の通信が行われています。

では、計算してみましょう。10,000 ユーザーがいて、全ユーザーが同時にページにアクセスした場合、1 秒あたりに 1,000 件の要求が発生するとします。どのユーザーも数秒おきに何かをクリックするため、毎秒、少なくとも 1,000 件以上の要求が Web ファームに送信されます。

1,000 件以上の要求が Web ファームに送信され、Web サーバーに送信されたすべての要求で、セッションの記憶域に対して 2 回の通信が行われるとします。したがって、Web の視点では、セッションの記憶域に対して 2,000 回以上の通信が発生していることになります。負荷がいかに急増し得るかがおわかりいただけるでしょう。これは、スケーラビリティのボトルネックが発生する可能性がある箇所の 1 つです。

スケーラビリティのボトルネックは、ページの実行中にアプリケーション データの読み取りや書き込みが必要になった場合にも、発生する可能性があります。たとえば、飛行機の空席情報について考えてみましょう。ユーザーが特定の区間の便を検索するためにページ上をクリックすると、アプリケーション データベースに対して複数の読み取りの通信が発生します。当然、次に、ユーザーは航空券の予約を行いますが、この場合、データがデータベースに書き込まれる必要があります。このデータは "アプリケーション データ" と呼ばれ、データベースに保存されます。この保存操作では、複数のデータ要素を保存するために、複数回のデータベース通信が発生する可能性があります。

したがって、最終的には、実際にユーザーが行った要求の 5、10、15、または 20 倍の数のデータベース通信が発生する可能性があります。つまり、データベースにかかる負荷はこのように格段に高く、これは大きなボトルネックになり得ます。

3 つ目のスケーラビリティのボトルネックは、SOA (サービス指向アーキテクチャ) 環境を使用していて、アプリケーションが別のサービス層を呼び出す場合に発生します。このサービス層は、同じデータ センター内にある場合も、別のデータ センターにある場合もあります。

通常、このサーバー層アーキテクチャには、サーバー ファームが使用されるため、Web アプリケーション アーキテクチャと同じようなスケーラビリティを備えています。しかし、サービス層は、独自のデータベースに依存しているため、アプリケーションと同様のスケーラビリティのボトルネックがあります。

つまり、アプリケーションは他のサービスに依存し、サービスは独自のデータベースに依存し、データベースにはスケーラビリティのボトルネックがあります。このように連携しているため、全体のスケーラビリティは最も低い部分と同じにしかなりません。独自のデータベースが原因でサービスを拡張できない場合、アプリケーションも拡張できません (図 1 参照)。

fig01.gif

図 1 Web ファームの拡張時にボトルネックになるデータベース

データベースが、メインフレームとリレーショナル データベースのどちらであるかは、あまり問題になりません。データ アクセスやデータ記憶域にはスケーラビリティがなく、Web テクノロジの拡張性について行くことができません。そして、このデータ記憶域のボトルネックが、ASP.NET アプリケーションの拡張を妨げています。

これらの問題が存在する理由

データ記憶域にスケーラビリティがない理由を考えてみましょう。まず、マイクロソフトが提供する 3 種類のセッション状態の記憶域のオプションを確認してみましょう。この 3 種類とは、InProc、StateServer、および SqlServer です。InProc には制限があります。これは、単一サーバーまたは単一プロセスの環境で使用することを想定したもので、複数サーバーまたは複数プロセスの ASP.NET 環境では機能しません。また、セッションは保持されません。

その場合、何が起こるかをご説明しましょう。ユーザーがあるサーバー上で操作を開始すると、そのサーバーでセッションが作成されます。その後、ロード バランサがユーザーを別のサーバーに割り当てた場合、アプリケーションでは、このセッションを見つけることができません。ユーザーは新たに操作を開始したと見なされ、再度ログインが求められます。ユーザーがクリック操作を行うたびにログインが必要になるため、ユーザーは先に進むことができず、アプリケーションは機能しません。

この問題を解決する方法の 1 つは、"固定セッション" 機能を使用することです。この機能を使用すると、常にユーザー要求を同じサーバーにルーティングできるため、アプリケーションがそのサーバー上のセッションを見つけることができます。

また、サーバーに Web ガーデンを作成しないことで、InProc の制限に対応することもできます。Web ガーデンは、アプリケーションに、同じサーバー上で実行される複数の ASP.NET ワーカー プロセスがある状態を言います。Web ガーデンを使用しないようにすると、プロセスは 1 つしか作成されず、少なくとも Web ファームで InProc を使用できるようになります。

しかし、これら 2 とおりの回避策は、理想的とは言えません。ユーザー セッションの長さは一様ではないことから、あるサーバーの負荷が別のサーバーに比べて高くなるため、固定セッションは、大きなスケーラビリティのボトルネックになり得ます。1 分間しかログインしないユーザーもいれば、20 分間ログインしているユーザーもいます。一部のサーバーでは多数のセッションを処理しますが、別のサーバーは事実上まったく使われません。サーバーを追加したとしても、スループットを向上できるとは限りません。

また、InProc にはメモリの制限もあります。ASP.NET プロセスのどのセッションも、メモリを必要とします。セッション数が増えるにつれて、ワーカー プロセスのメモリ要件も格段に大きくなります。ただし、32 ビット プラットフォームでは、ワーカー プロセスに 1 GB のメモリ制限があり、これが問題になります。他のデータやアプリケーション コードを含めて、1 GB のワーカー プロセス メモリに収まらないセッション データを扱うことはできません。したがって、InProc はボトルネックになります。そして、ユーザーが増えれば増えるほど、このような問題が発生する頻度も高くなります。

StateServer の場合は、ASP.NET ワーカー プロセスとは別のプロセスにセッション状態が保存されますが、StateServer にも制限があります。すべての Web サーバーに独自の StateServer が保持されるように構成することも、専用のサーバーを用意して、セッション状態をそのサーバーにのみ保存するようにすることもできます。

1 つ目の構成では、やはり固定セッションを使用しなければならないことが問題です。必ずセッションが作成された場所に、戻る必要があります。また、1 つ目の構成は、InProc Web ガーデンの制限を緩和するに過ぎません。一部のサーバーに負荷が集中し、使用されないサーバーが存在するという固定セッションの問題は解決されません。結局、ユーザーのセッションと応答に、非常に時間がかかるようになります。

この構成には、ある Web サーバーが停止した場合、その Web サーバーの StateServer も停止するため、そのサーバーのすべてのセッションが失われるという、もう 1 つの問題があります。確かに、Web サイトのセッションすべてが失われるわけではありませんが、そのサーバーに保存されていたセッションはすべて失われることになり、これは許容できるものではありません。できれば、どのセッションも失いたくありません。

専用の StateServer サーバーを用意するという StateServer のもう 1 つの構成では、すべての Web サーバーが同じ専用サーバーを使用するため、固定セッションを使用する必要がありません。ただし、これには、さらに大きな問題があります。この専用サーバーが停止した場合、すべての Web サーバーでは、このサーバーからセッションを取得しようとするため、Web ファーム全体が停止することになります。

それだけではありません。新しい Web サーバーが追加され、1 秒あたりのトランザクション数が増加するにつれて、この StateServer 専用サーバーには処理できないほどの負荷がかかるようになります。結果として、瞬く間にスケーラビリティのボトルネックになります。したがって、スケーラビリティの問題は、どちらの構成を使用しても、StateServer では解決できません。

では SqlServer を見てみましょう。SqlServer では、SQL Server データベースにセッション状態が保存され、専用の StateServer サーバーと見なすことができます。SQL Server は、高度なトランザクション環境向けのマイクロソフトの主力データベース サーバーです。SQL Server では、データベース サーバー クラスタを作成できるため、StateServer よりもスケーラブルです。

SqlServer 構成では、実際には、すべてのセッションが保存されている SqlServer 専用サーバーにすべての Web サーバーが接続します。これは、各 Web サーバーが StateServer 専用サーバーに接続しているのと同様の状態です。この構成は、SqlServer が StateServer よりもスケーラブルであるという概念に基づいています。しかし、SqlServer は StateServer ほど処理が高速ではありません。StateServer はメモリ内データ ストアであるため、十分なパフォーマンスを備えています。これに対して、SqlServer はメモリ内データ ストアではなく、ディスク ベースのデータ ストアです。データベースは、メモリ内にデータベース全体を保持できないほどサイズが大きくなるため、すべてのデータベースはディスク上に保存されます。したがって、データベースのデータは、永続記憶装置、つまりディスクに保存されます。ディスクに保存されるために、SqlServer のパフォーマンスは StateServer ほど高速ではなく、結果としてパフォーマンスが低下します。

SqlServer は複数の構成が可能です。最も一般的なスタンドアロン構成では、1 台のデータベース サーバーのみを用意し、このサーバーにすべての Web サーバーがアクセスします。この場合、Web ファームが拡大し、Web サーバーの台数が増えるに従い、データベースの負荷も増大します (図 2 参照)。

fig02.gif

図 2 ASP.NET セッションは依然としてボトルネックであり、データベースも完全にスケーラブルではない

そのほか、SqlServer は、メモリ ベースではないためにパフォーマンスの問題があります。また、十分にスケール アウトできないためにスケーラビリティの問題もあります。サーバーに CPU を追加し、ハードウェアの性能を強化することで、スケール アップすることはできますが、Web ファームの拡大に合わせて、データベース サーバーを追加し続けることはできません。サーバーを 1 台から 2 台または 2 台から 3 台に増やして、SqlServer によってデータベース クラスタ機能を提供することは可能で、これは StateServer 以上の拡張が可能ですが、この構成にも制限があります。

SqlServer 記憶域のもう 1 つの問題は、すべてのセッションが 1 つのテーブルに保持されることです。スケール アップした途端に、セッション データの同時実行アクセスや同時更新時に、ロックの競合の問題が表面化します。すべてのセッションが 1 つのテーブルに保持されているため、1 秒あたりのトランザクションが増えるほど、ロックに伴う遅延も頻繁に発生します。

したがって、SqlServer は StateServer よりもスケーラブルですが、パフォーマンスの問題があり、十分なスケーラビリティも得られません。また、拡張内容に比例した効果が得られるわけではありません。Web ファームのサーバーを 5 台から 50 台や 100 台まで増やすことが可能で、Web ファーム自体は問題なく拡張できますが、データ アクセスはそれに合わせて拡張されません。前述のとおり、データベースは、拡張できないデータ記憶域アクセスの 1 つであるため、データベースにセッションを保存しても大きな改善は見られず、StateServer 環境よりも多少改善される程度です。また、SqlServer は、アプリケーション データとセッション データのどちらについても、ボトルネックになります。したがって、セッション データとアプリケーション データのどちらについても、データベース サーバーは拡張できません。

解決策

解決策は、メモリ内の記憶域メカニズムです。これにより、StateServer と同等の非常に高速な処理を実現できます。しかし、実質的に、拡張内容と比例して効果が得られるものである必要があります。比例した効果が得られるスケーラビリティとは、サーバーを追加した分だけ、容量も比例して増加することを意味します。たとえば、1 台のサーバーで 1 秒間に 10,000 件のトランザクションを処理できる場合、2 台目のサーバーを追加すると、合計で 1 秒間に 20,000 件近くのトランザクションを処理できるということです。"実質的に比例する" ということは正確に 20,000 というわけではなく、19,000 という場合もあります。ただし、12,000 や 15,000 ではありません。必要なのは、ほぼ比例して拡張でき、メモリ内にある記憶域です。

この 2 つの要件により、別の要件を持ち長期の保存を目的とした永続記憶装置は対象外とします。データベースは長期保存を目的としていますが、メモリ内の記憶域は常に一時的なものです。しかし、ここで必要なのは一時的な記憶域です。ユーザー セッションの間、またはおそらくアプリケーションが実行されている間、数時間から数日または長くても数週間、この一時記憶域にデータを保存しておけばよいのです。また、必ずマスタの永続記憶域があるため、このデータは消去されてもかまいません。マスタ記憶域はデータベースで、そこからこのデータを読み込むことができます。

このすべてを考慮すると、"分散キャッシュ" という記憶域メカニズムが思い浮かびます。これは上記の特性を備えているため、よく利用されるようになっている概念です (図 3 参照)。

fig03.gif

図 3 データベース サーバーの負荷を軽減する分散キャッシュ

分散キャッシュはメモリ内の記憶域なので、高速で、特に適切な分散メカニズム (キャッシュ トポロジ) がある場合、かなり比例的に負荷を分散できるように設計されています。

分散キャッシュは、高いパフォーマンスと比例的なスケーラビリティを実現する必要があります。また、メモリ内に存在するため、レプリケーションも必要です。これにより、あるコンピュータが停止した場合 (このコンピュータのメモリが利用できなくなった場合) に、別のコンピュータにそのデータがあり、データが失われないようにします。レプリケーションでは、データのコピーが、複数のサーバーの個別の領域に保存されます。レプリケーションを行うことで、データ保存期間中に 100% の稼働時間を実現できます。

分散キャッシュでは、.NET オブジェクトまたは Java オブジェクトが保存されるか、XML ドキュメントのようなデータが保存されます。データは、あらかじめ用意された形式で保存されます。分散キャッシュには、テーブル、行、主キー、外部キーといった、データベースにある概念はありません。プログラマにとっては、分散キャッシュは基本的にハッシュ テーブルです。ハッシュ テーブルにはキーがあり、各キーには値があり、この値はオブジェクトです。キーは把握しておく必要があり、このキーを基に、必要なオブジェクトをフェッチします。これは、複数のサーバーにまたがる 1 つの論理キャッシュです。何かを停止することなく、同時に複数台のサーバーを追加してキャッシュ クラスタのサイズを増やすことも、同時に複数台のサーバーを削除してキャッシュ クラスタを縮小することもできます。

キャッシュ トポロジ

有用なキャッシュとして利用できるさまざまなトポロジとしては、レプリケーション キャッシュ、パーティション キャッシュ、レプリケーションとパーティションの混合キャッシュ、およびクライアントまたはローカル キャッシュがあります。使用状態に合わせてキャッシュのトポロジを変えることができるように、キャッシュは非常に柔軟性が高くなっています。レプリケーション トポロジは、必要な回数に応じて、何度でもキャッシュをレプリケートします (図 4 参照)。レプリケーション トポロジは、キャッシュの使用状態が、読み取りが多く、更新が多くない場合に使用します。

fig04.gif

図 4 レプリケーション キャッシュは読み取りが多い場合に適している

パーティション キャッシュは、キャッシュされる必要がある、更新が多いデータやトランザクション データに適した、非常にスケーラブルなトポロジです。トランザクションが多い ASP.NET セッション データが、このようなデータの一例です。前述のとおり、どの Web 要求でも、セッションの読み取りと更新が 1 回ずつ行われるため、読み取りと書き込みの回数は同じになります。

パーティション トポロジ (図 5 参照) は、更新の回数が、少なくとも読み取りの回数と同じか近い環境に適しています。このトポロジでは、キャッシュが分割されます。キャッシュ サーバーの追加台数に応じてキャッシュは細かく分割され、キャッシュ全体のほぼ 1/N (N はノード数) が、各キャッシュ サーバーに保存されます。

fig05.gif

図 5 パーティション キャッシュは書き込みが多い場合に適している

3 つ目のトポロジは、パーティションとレプリケーションの混合バージョンです。キャッシュをパーティションに分割しながら、各パーティションをレプリケートできます。したがって、両方のキャッシュの長所を併せ持っています。パーティション分割して拡張できるだけでなく、データが失われることがないようにレプリケーションにより可用性を確保できます (図 6 参照)。

fig06.gif

図 6 パーティションとレプリケーションの混合キャッシュは、高い信頼性が必要で書き込みが多い場合に適している

パーティション トポロジおよびパーティションとレプリケーションの混合トポロジを利用すると、スケーラビリティの点では、キャッシュを比例的に拡張できます。

クライアントまたはローカル キャッシュは、4 つ目の有用なトポロジで、これはアプリケーション サーバーに置かれます。このキャッシュはアプリケーションに非常に近く、InProc にもなり得ます。これは、通常、大きな実際の分散キャッシュのごく一部であり、ある特定の時点でアプリケーションが要求している内容に基づいたキャッシュです。アプリケーションから要求されたものは、コピーがクライアント キャッシュに保持されます。アプリケーションが次に同じデータを要求したときには、クライアント キャッシュにあるデータが自動的に検出されます。分散キャッシュは、多くの場合、ネットワークを隔てた別のキャッシュ サーバーやキャッシュ サーバーのクラスタにありますが、分散キャッシュにアクセスする必要がないため、その分の通信も省略できます。クライアント キャッシュでは、パフォーマンスとスケーラビリティが向上します。

クライアント キャッシュ内のデータは、分散キャッシュと同期されている必要があります。同じデータが分散キャッシュ内で変更された場合、分散キャッシュでは、この変更をクライアント キャッシュと同期する必要があります。この点は重要です。完全に分断されたローカル キャッシュのみを利用するのは適切ではありません。これは InProc キャッシュとまったく同じで、データの整合性に問題があるため不適切です。同じデータでありながら同期されていない複数のバージョンが存在することになります。

別の選択肢

利用できる分散キャッシュ機能は複数あります。また、ほとんどの場合、無償のソリューションは機能が限られており、市販のソリューションの方が格段に多くのオプションと機能を提供します。

パフォーマンス、スケーラビリティ、可用性の高さだけでなく、効率的な分散キャッシュは、キャッシュを最新の状態に保ち、データベースであれ、メインフレームであれ、マスタのデータ ソースと同期するためのいくつかの主要な機能を備えている必要があります。有効期限オプションを備え、絶対時刻または "スライド時刻" と呼ばれるものにより、自動的に有効期限が切れるように設定できる必要があります。基本的にこれはアイドル時間です。特定のデータが使用されていない場合、自動的に有効期限切れになります。

キャッシュは、種類の異なるデータ間のリレーションシップも管理できる必要があります。ほとんどのデータは、リレーショナルです。たとえば、顧客がいる場合、その顧客からの注文もあるため、顧客データと注文データ間にリレーションシップがあります。顧客データと注文データの両方をキャッシュしていて、キャッシュから誤って顧客データを削除した場合、注文も自動的に削除されるのが適切でしょう。この例では、顧客データをキャッシュから削除しただけなのか、完全に削除したのかは、わかりません。完全に削除した場合、注文は有効な顧客から出されたものである必要があるため、注文も無効になります。

他にも、キャッシュで管理する必要がある同様のリレーションシップがあります。キャッシュで管理されない場合、アプリケーションにより管理する必要がありますが、これは非常に面倒です。マイクロソフトが提供する ASP.NET のキャッシュ オブジェクトは非常に便利で、これは "キャッシュ依存関係" と呼ばれます。あるキャッシュ項目は、別のキャッシュ項目に依存します。この依存されているキャッシュ項目が、キャッシュから削除されるか更新された場合、依存している項目も削除されます。これは強力なキャッシュの依存関係であり、リレーショナル データをキャッシュするキャッシュには必ず実装するようにしてください。

データベースとの同期も、キャッシュにとって重要な機能の 1 つです。通常、データベースは、複数のアプリケーションが共有しています。キャッシュを使用しているアプリケーションしか、データベースを更新しない場合、データベースの同期機能はおそらく不要です。しかし、データベースは共有ストアであるため、通常は他のアプリケーションがデータベースのデータを更新しますが、これらのアプリケーションはこのキャッシュを使用しません。これらは、サードパーティ製のアプリケーションである場合もあれば、.NET アプリケーションでさえない場合もあります。アプリケーションが、サードパーティ製のもので制御できないアプリケーションであっても、データベースのデータは更新されます。そこで、自分のアプリケーション以外によってデータベースが更新される可能性があり、データベース内で更新されたデータの一部がキャッシュされている状況を考慮する必要があります。したがって、キャッシュは同期できる必要があります。キャッシュに含まれるデータが、データベース内のデータと同じでなくなったときには、そのことを必ず認識できる必要があります。問題のデータをキャッシュから削除する必要があり、場合によっては、データベースから最新のデータを再び読み込むまでの処理が必要です。データベースの同期は、データベース サーバーで発生するイベントまたはデータベースをポーリングするキャッシュによって、実行できます。イベントはリアルタイムですが、ポーリングにはわずかに遅延があります。ただし、多くのデータが変更される場合は、ポーリングの方が効率が良い場合があります。

イベント通知は、有用な分散キャッシュに必要な機能のうち、最も重要なものの 1 つです。キャッシュは複数のアプリケーション間で共有されることが多く、さらに 1 つのアプリケーション内でも複数のユーザー間で共有されることがあります。したがって、たとえば、キャッシュ オブジェクトが更新または削除された場合に備えて、キャッシュにはイベント通知メカニズムが必要です。アプリケーションが同じデータを使用している場合は、データベースから再度読み込んだり、キャッシュ自体から新しいコピーを再度読み込めるように、通知を利用することをお勧めします。通知メカニズムを使用することで、キャッシュを利用した複数のユーザーやアプリケーション間の共同作業機能が向上されます。

実際の使用

IT 管理では、データベースに関するパフォーマンスの問題すべてに取り組む必要があります。ボトルネックがある場合は、運が良ければ開発者に報告して、開発者が解決を図る場合があります。しかし、残念ながら、開発は社内で行われているとは限りません。多くの場合、サードパーティ製のアプリケーションを利用および管理しています。

どのような場合でも、ボトルネックを解消してアプリケーションを最適化するために、分散キャッシュを実装する場合は、ASP.NET セッションの記憶域から取り掛かるのが最適です。これは、開発者を頼る必要がないためです。プログラミングは必要なく、必要なのは、既存のセッション記憶域を、メモリ内の分散キャッシュに置き換えるだけです。また、ASP.NET セッションの記憶域として分散キャッシュを実装すると、パフォーマンスとスケーラビリティの面で得られるメリットを確認することができ、アプリケーション データについても同様に対応するかどうかを決定できます。

実際にスケーラビリティの向上を確認するには、分散キャッシュ記憶域を運用環境で実行するか、テスト環境で運用時の負荷をシミュレーションする必要があります。QA を利用できる場合もあります。これは、分散キャッシュを運用環境に実装する前に、高負荷をシミュレーションするストレス テストをテスト環境で実行する場合に便利です。ほとんどの IT 管理者は、まったく同じ負荷をシミュレーションできないとしても、まず QA 環境で分散キャッシュをテストしないと、安心して運用環境に分散キャッシュを実装できないでしょう。したがって、この作業から着手すると良いでしょう。

分散キャッシュを実装し、そのメリットを享受できるようになったら、新たに実現された ASP.NET セッションのパフォーマンスとスケーラビリティについての情報を社内やサードパーティ ベンダの開発チームと共有できます。確かな証拠があれば、この分散キャッシュにアプリケーション データもキャッシュできる領域を分析するように開発チームに依頼できます。

アプリケーション データをキャッシュすると、パフォーマンスを向上でき、多くの場合、単に ASP.NET セッション記憶域に分散キャッシュを使用する場合よりも、はるかにパフォーマンスが向上します。開発者は、更新よりも読み取りの頻度が高いデータ要素をすべて特定できるようになります。トランザクション データ (顧客、注文など) でさえも、キャッシュ対象の候補です。これは、キャッシュに保持される期間が数分で、有効期限切れになるとしても、当てはまります。この短時間の間に、データが何度も再読み取りされる可能性がある場合、データベースでなくキャッシュからデータが再度読み取られれば、データベースにかかる読み取りの負荷を大幅に軽減できます。

ただし、アプリケーション データをキャッシュするには、分散キャッシュに対する API 呼び出しを行うために、開発者による多少のプログラミングが必要です。考え方は非常に単純です。アプリケーションがデータベースからデータをフェッチする際に、必ず最初にキャッシュを確認するようにします。キャッシュに目的のデータがある場合、キャッシュからデータを取得します。キャッシュにデータがない場合、アプリケーションでは、データベースからデータをフェッチし、このデータをキャッシュしてから、ユーザーに提供します。このようにすることで、次にこのデータが読み取られるときに、データがキャッシュから見つかります。同様に、データがデータベース内で変更された場合、必ずキャッシュ内のデータも更新される必要があります。また、キャッシュが複数のサーバーにある場合、キャッシュは自動的に同期される必要があります。これにより、アプリケーションが Web ファーム内で実行されている場合に、ファーム内のすべてのサーバーから同じキャッシュ データにアクセスできるようにします。スケーラビリティを向上する目的で分散キャッシュを使用するアプリケーションを開発する方法の詳細については、MSDN Magazine の 7 月号に掲載予定の私が執筆した記事を参照してください。

Iqbal Khan は Alachisoft の代表取締役を務めている、テクノロジ エバンジェリストです。同社は、業界をリードする .NET 分散キャッシュ製品の NCache を提供しています。NCache は、エンタープライズ アプリケーションのパフォーマンスとスケーラビリティを向上する製品です。Iqbal は、1990 年にインディアナ大学 (所在地: ブルーミントン) において理学修士号を取得しています。連絡先は、iqbal@alachisoft.com (英語のみ) です。