JavaエンタープライズパフォーマンスにMemcachedを使用するパート1:アーキテクチャとセットアップ

LiveJournal.comのサイトパフォーマンスを向上させるためにDangaInteractiveによって開発された、Memcachedの分散アーキテクチャは、今日、Twitter、Facebook、WikipediaなどのソーシャルWebアプリケーションの指数関数的なスケーラビリティをサポートしています。この2部構成のチュートリアルでは、Sunil PatilがMemcachedの分散ハッシュテーブルアーキテクチャを紹介し、それを使用して独自のデータベース駆動型Javaエンタープライズアプリケーションのデータをキャッシュする方法を説明します。

このチュートリアルでは、Memcachedを使用してJavaエンタープライズアプリケーションのパフォーマンスを向上させる方法を紹介します。前半は、Memcachedのアーキテクチャと比較した従来のJavaキャッシングアーキテクチャの概要から始まります。また、Memcachedをマシンにインストールし、Telnet経由でMemcachedを操作するためのセットアップとコマンドを紹介します。後半では、Javaで「HelloMemcached」クライアントプログラムを開発します。これを使用して、spymemcachedクライアントの内部を調べます。また、Memcachedを使用してデータベースサーバーの負荷を軽減し、Memcachedを使用して動的に生成されたページマークアップをキャッシュする方法についても学習します。最後に、spymemcachedクライアントを構成するためのいくつかの高度なオプションについて検討します。

JavaWorldでのJavaキャッシングの詳細

  • Memcachedを使用した分散キャッシュの詳細については、「サーバー負荷分散アーキテクチャ、パート1:トランスポートレベルの負荷分散」を参照してください。
  • 従来のJavaキャッシングについては、「オープンソースJavaプロジェクト:Javaキャッシングシステム」も参照してください。

MemcachedおよびJavaキャッシングアーキテクチャの概要

EHCacheやOSCacheなどのJavaキャッシングフレームワークは、基本的にHashMapアプリケーションコード内のオブジェクトです。キャッシュに新しいオブジェクトを追加するたびに、そのオブジェクトはアプリケーションのメモリに保存されます。この戦略は、少量のデータを格納する場合は正常に機能しますが、数ギガバイト(GB)を超えるキャッシュには機能しません。Memcachedサーバーの設計者は、システムのスケーラビリティを可能にする分散アーキテクチャアプローチを採用しました。その結果、Memcachedを使用して大量のデータをキャッシュできます。

Memcachedのアーキテクチャは2つの部分で構成されています。 1つは、独自のプロセスで実行されるMemcachedサーバーです。アプリケーションをスケーリングする場合は、Memcachedサーバーを追加のマシンにインストールして実行できます。 Memcachedサーバーのインスタンスは相互に認識していません。 Memcachedのクライアント、memcachedのシステムの第二の部分は、ないサーバのそれぞれについて知っています。クライアントは、キャッシュエントリごとにサーバーを取得し、キャッシュエントリを保存または取得する責任があります。このプロセスについては、この記事の後半で詳しく説明します。

Java EE Webアプリケーションでの作業経験がある場合は、以前にEHCacheやOSCacheなどのオープンソースのJavaキャッシングフレームワークを使用したことがある可能性があります。DynaCache(IBM WebSphere Application Serverに付属)やJBoss Cache(JBoss ASに付属)など、アプリケーションサーバーの一部として出荷された商用キャッシュフレームワークを使用した可能性もあります。このチュートリアルの実践的な学習部分に入る前に、Memcachedがこれらの従来のJavaキャッシングフレームワークとどのように異なるかを理解することが重要です。

従来のJavaキャッシュを使用する

オープンソースまたは商用オプションのどちらを選択したかに関係なく、従来のJavaキャッシングフレームワークの使用は非常に簡単です。 EHCacheやOSCacheなどのオープンソースフレームワークの場合、バイナリをダウンロードし、必要なJARファイルをアプリケーションのクラスパスに追加する必要があります。また、キャッシュのサイズやディスクのオフロードなどを構成するために使用する構成ファイルを作成する必要がある場合もあります。アプリケーションサーバーにバンドルされているキャッシングフレームワークの場合、通常、追加のJARはソフトウェアにバンドルされているため、ダウンロードする必要はありません。

アプリケーションにキャッシュフレームワークのサポートを追加した後、CacheManagerオブジェクトを作成し、その中にキャッシュエントリを取得して設定することで、キャッシュフレームワークの使用を開始できます。内部的には、キャッシングフレームワークはCacheManager、アプリケーションが実行されていたのと同じJVMにオブジェクトを作成します。キャッシュエントリを追加するたびに、そのオブジェクトは、キャッシュフレームワークによって維持されるある種のハッシュテーブルにも追加されます。

アプリケーションサーバーが複数のノードで実行されている場合は、分散キャッシュのサポートも必要になる場合があります。分散キャッシュシステムでは、AppServer1のキャッシュにオブジェクトを追加すると、そのオブジェクトはAppServer2とAppServer3でも使用できます。従来のJavaキャッシュは、分散キャッシュにレプリケーションを使用します。つまり、AppServer1にキャッシュエントリを追加すると、システム内の他のアプリサーバーに自動的にレプリケートされます。その結果、エントリはすべてのノードで使用できるようになります。

Memcachedの使用

キャッシュにMemcachedを使用するには、最初に、選択したプラットフォーム用のMemcachedサーバーをダウンロードしてインストールする必要があります。Memcachedサーバーをインストールすると、TCPまたはUDPポートでキャッシュ呼び出しをリッスンします。

次に、Memcached用のJavaクライアントをダウンロードし、クライアントJARをアプリケーションに追加します。その後、Memcachedクライアントオブジェクトを作成し、そのメソッドの呼び出しを開始して、キャッシュエントリを取得および設定できます。オブジェクトをキャッシュに追加すると、Memcachedクライアントはそのオブジェクトを取得してシリアル化し、ストレージ用にバイト配列をMemcachedサーバーに送信します。その時点で、キャッシュされたオブジェクトは、アプリケーションが実行されているJVMから収集されたガベージである可能性があります。

キャッシュされたオブジェクトが必要な場合は、Memcachedクライアントのget()メソッドを呼び出すことができます。クライアントはgetリクエストを受け取り、シリアル化して、Memcachedサーバーに送信します。 Memcachedサーバーは、リクエストを使用してキャッシュからオブジェクトを検索します。オブジェクトを取得すると、バイト配列をMemcachedクライアントに返します。次に、Memcachedクライアントオブジェクトはバイト配列を取得し、それを逆シリアル化してオブジェクトを作成し、アプリケーションに返します。

アプリケーションが複数のアプリケーションサーバーで実行されている場合でも、それらすべてが同じMemcachedサーバーをポイントし、それを使用してキャッシュエントリを取得および設定できます。 Memcachedサーバーが複数ある場合、サーバーはお互いを認識しません。代わりに、Memcachedクライアントを構成して、使用可能なすべてのMemcachedサーバーを認識できるようにします。たとえば、アプリケーションがAppServer1でJavaオブジェクトを作成し、set()Memcachedのメソッドを呼び出す場合、Memcachedクライアントは、そのエントリがどのMemcachedサーバーに移動するかを判断します。その後、そのMemcachedサーバーとのみ通信を開始します。同様に、AppServer2またはAppServer3のコードがgetエントリを試行すると、Memcachedクライアントは最初にそのエントリが保存されているサーバーを特定し、次にそのサーバーとのみ通信します。

Memcachedクライアントロジック

デフォルトの構成では、Memcachedクライアントは非常に単純なロジックを使用して、取得または設定操作用のサーバーを選択します。あなたが作るときget()set()通話を、クライアントがキャッシュキーを受け取り、その呼び出しhashCode()、そのようなことは、その数と利用できるのMemcachedサーバの数で割り、それを取る11として整数を取得する方法を、2を言います。次に、余りの値(この場合は1)を取ります。キャッシュエントリはMemcachedサーバー1に送られます。この単純なアルゴリズムにより、各アプリケーションサーバーのMemcachedクライアントは、特定のキャッシュキーに対して常に同じサーバーを選択します。

Memcachedのインストール

Memcachedは、Unix、Linux、Windows、およびMacOSXで実行されます。Memcachedソースをダウンロードしてコンパイルするか、他の誰かがコンパイルしたバイナリをダウンロードして、それらを使用してMemcachedをインストールすることができます。ここでは、選択したプラットフォームのバイナリをダウンロードするプロセスについて説明します。ソースからコンパイルする場合は、「参考文献」を参照してください。

次のインストール手順は、Windows XP32ビットマシン用です。Linuxなどの他のプラットフォームのインストール手順については、「参考文献」を参照してください。また、この記事のサンプルコードは、Windows XP 32ビットマシンで開発されましたが、他のプラットフォームでも機能するはずです。

  1. Jellycanコードには、操作が簡単で効率的なMemcachedの修正バージョンがあります。ここから、win32バイナリZIPファイルをダウンロードしてください。
  2. 展開しMemcached--win32-bin.zip、あなたのハードディスク上。含まれているのはmemcached.exe。だけであることに注意してください。このファイルを実行して、Memcachedサーバーを起動します。
  3. 次にmemcached.exe -d install、memcached.exeをサービスとして登録するために実行します。サービスコンソールを使用して、Memcachedサーバーを起動および停止できます。

CLスタート/ストップ

サービスパネルからではなく、コマンドラインからMemcachedサーバーを起動および停止してみてください。そうすることで、さまざまなコマンドラインオプションを試して、要件に最適な構成を見つけるための柔軟性が高まります。

memcached.exeコマンドラインオプションなしで実行すると、デフォルトでは、Memcachedサーバーは64MBのメモリを備えたポート11211で起動します。場合によっては、構成をよりきめ細かく制御したいことがあります。たとえば、ポート11211がマシン上の他のプロセスによって使用されており、Memcachedサーバーがポート12000を使用するようにしたいとします。または、QAまたは本番環境でMemcachedサーバーを起動する場合は、デフォルトの64MBよりも多くのメモリを割り当てたいと思うでしょう。このような場合、コマンドラインオプションを使用してサーバーの動作をカスタマイズできます。memcache.exe -helpコマンドを実行すると、図3に示すようなコマンドラインオプションの完全なリストが表示されます。

Telnet経由でMemcachedに接続する

Memcachedサーバーが起動すると、割り当てたポートでリッスンします。Memcachedクライアントは、TCPポートまたはUDPポートのいずれかでサーバーに接続し、コマンドを送信して応答を受信し、最終的に接続を閉じます。(クライアントがサーバーとの通信に使用するプロトコルの詳細については、「参考文献」を参照してください。)

Memcachedサーバーにはさまざまな方法で接続できます。このチュートリアルの後半で行うように、Javaクライアントを使用している場合は、キャッシュからオブジェクトを格納および取得するための単純なAPIにアクセスできます。または、Telnetクライアントを使用してサーバーに直接接続することもできます。Telnetクライアントを使用してMemcachedサーバーと通信する方法を知ることは、Javaクライアントをデバッグするために重要なので、ここから始めます。

Telnetコマンド

まず、選択したTelnetクライアントを使用してMemcachedサーバーに接続する必要があります。Windows XPマシンでtelnet localhost 11211は、Memcachedサーバーが同じマシンで実行されており、デフォルトの11211ポートでリッスンしていると仮定して簡単に実行できます。Telnet経由でMemcachedを操作するには、次のコマンドが不可欠です。

  • setキャッシュに新しいアイテムを追加します。呼び出しは次のとおりSet です。次の行に保存する必要のある実際の値を入力できます。キャッシュエントリを期限切れにしたくない場合は、値として0を入力します。
  • getキャッシュキーの値を返します。get の値を取得するために使用しますkeyName
  • add新しいキーがまだ存在しない場合にのみ追加します。例えば:add
  • replaceキーが存在する場合にのみ値を置き換えます。例えば:replace
  • deleteキーのキャッシュエントリを削除します。この呼び出しdelete を使用して、の値を削除できますkeyName

図4のスクリーンショットは、Telnetを介したMemcachedサーバーとの相互作用の例を表しています。あなたが見ることができるように、memcachedサーバのような、各コマンドにフィードバックを提供しSTOREDNOT_STOREDなど。

パート1の結論

これまで、Memcachedの分散アーキテクチャと従来のJavaキャッシュシステムの違いについて簡単に説明してきました。また、開発環境にMemcached実装をセットアップし、Telnet経由でMemcachedに接続する練習をしました。このチュートリアルの次のパートでは、Javaクライアントspymemcachedを使用して、サンプルJavaアプリケーションの分散キャッシュソリューションをセットアップします。その過程で、Memcachedと、それがJavaEEアプリケーションのパフォーマンスをどのように改善できるかについてさらに多くを学びます。

Sunil Patilは、カリフォルニア州サンフランシスコのAvnetTechnologyで働くJavaEEアーキテクトです。彼はJavaPortlets 101(SourceBeat、2007年4月)の著者であり、JavaWorld、IBM DeveloperWorks、およびO'ReillyMediaによって発行された多数の記事を執筆しています。彼は、IBM認定のWebSphere Portal Serverアプリケーション開発者および管理者であることに加えて、Sun Microsystems認定のJavaプログラマー、Webコンポーネント開発者、およびビジネスコンポーネント開発者でもあります。Sunilのブログは//www.webspherenotes.comで見ることができます。