Ehcacheとterracottaの連携を試してみた。
大量のアクセスがあるWebサービスを運用している場合に、DBの負荷が非常に高くなっている場合がある。
RDBMSはスケールアウトしずらく、スケールアップでその高負荷に対応するなどして、ボトルネックを解消しようとすると思う。
RDBMSの高負荷の解消のためには、キャッシュ機構を使用して、DBへのアクセスを減らすという方法がある。
キャッシュ機構には、自分の知っているものは下記がある。
Ehchace
オープンソースの分散キャッシュサーバ。
memcachedと比べると、多機能である。
●キャッシュ方法
ディスクキャッシュ、メモリキャッシュをサポートする。
(※memcachedはメモリキャッシュのみ)
●キャッシュの追い出しポリシー
- LRU(Last Recently Used)
最後に参照された日時が最も古い順に削除する。
- LFU(Last Frequently Used)
参照された回数が最も少ない要素から順に削除する。
- FIFO(First In First Out)
要素がキャッシュに追加された順に削除する。
※memcachedはLRUが採用されている。
●レプリケーション
RMI(Remote Method Invocation)や、JMS(Java Message Service)を使用してレプリケーション・キャッシュ*1を実現することができる。
また、後で記述するが、Terracottaを用いたレプリケーションも可能である。
●その他機能
トランザクション、ロック、モニタリング等の機能も存在する。
Terracotta
複数のJVM間でJavaオブジェクトのクラスタリングを行う。
また、HiberfnateやSpringとの連携も容易である。(各ミドルウェア向けのモジュールが提供されている)
Ehcacheのインストール
現在、最新のバージョンは2.4.2。
今回はmaven2を使用してプロダクトをインストールする。
pom.xmlに下記を追記する。
<repository> <id>terracotta-release</id> <url>http://repo.terracotta.org/maven2</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>false</enabled></snapshots> </repository> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.4.2</version> <type>pom</type> </dependency>
また、APIでslf4jを使用しているので、下記も追記する。
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.1</version> </dependency>
Terracottaのインストール
terracottaサーバの起動のために、Terracottaサイトから下記をダウンロードする。
現在の最新バージョンは3.5.1。
terracotta-3.5.1-installer.jar
下記コマンドでインストールする。
java -jar terracotta-3.5.1-installer.jar
また、TerracottaのruntimeAPIをダウンロードするために、pom.xmlに下記を記述する。
<dependency> <groupId>org.terracotta</groupId> <artifactId>terracotta-toolkit-1.2-runtime-ee</artifactId> <version>3.1.0</version> </dependency>
EhcacheとTerracottaの連携
下記のような構成の場合のEhcacheとTerracottaの連携方法をサンプルとして記述します。
●設定ファイルの作成
EhcacheとTerracottaを連携するためには、ehcache.xmlを作成する必要がある。
ehcache.xmlはクラスパスのルート位置に作成する。
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect"> <!-- ディスクキャッシュ時のデータ保存領域 --> <diskStore path="java.io.tmpdir"/> <!-- terracottaの設定 --> <!-- <terracottaConfig url="localhost\:9510, your.domain:9510" /> --> <terracottaConfig> <tc-config> <system> <configuration-model>development</configuration-model> </system> <servers> <server host="localhost" name="server1"> <!-- permanent-store(ディスクに保存)に設定しないと再接続ができない。 --> <dso> <persistence> <mode>permanent-store</mode> </persistence> </dso> </server> <server host="your.domain" name="server2"> <dso> <persistence> <mode>permanent-store</mode> </persistence> </dso> </server> </servers> <clients> <logs>C:\app\logs-%i</logs> </clients> </tc-config> </terracottaConfig> <!-- デフォルトキャッシュ --> <defaultCache /> <!-- name: キャッシュ名 eternal:キャッシュオブジェクトの有効期限の有無(true:無) maxElementsInMemory:メモリ上にキャッシュするオブジェクトの最大数(0の場合は無制限) maxElementsOnDisk:ディクス上にキャッシュするオブジェクトの最大数(0の場合は無制限) overflowToDisk:キャッシュオブジェクトの最大数を超えた時、Diskに保持するかどうか。(true:する) ※terracottaを使用する場合はfalseに設定する。 timeToIdleSeconds:未アクセスの削除期限 timeToLiveSeconds:キャッシュオブジェクトの寿命 memoryStoreEvictionPolicy:メモリに格納するエントリが最大値に達したときの振る舞い(LRU、FIFOまたは、LFU) --> <cache name="terracottaTest" eternal="false" maxElementsInMemory="1000" maxElementsOnDisk="10000" overflowToDisk="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600" memoryStoreEvictionPolicy="LFU"> <!-- terracottaを使用する --> <terracotta clustered="true" valueMode="serialization" consistency="strong" storageStrategy="DCV2"> <!-- 読み取り中にタイムアウトした場合は、ローカルから読み取る設定 --> <nonstop enabled="true" immediateTimeout="false" timeoutMillis="1000"> <timeoutBehavior type="localReads" /> </nonstop> </terracotta> </cache> </ehcache>
次に、Terracottaの設定ファイル「tc-config.xml」を任意の位置に作成する。
serversタグで書かれたサーバの起動順によって、アクティブサーバとスタンバイサーバになる。
tc-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <tc:tc-config xmlns:tc="http://www.terracotta.org/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-6.xsd"> <system> <configuration-model>development</configuration-model> </system> <servers> <server host="localhost" name="server1"> <data>%(user.home)/terracotta/server-data</data> <logs>%(user.home)/terracotta/server-logs</logs> </server> <server host="your.domain" name="server2"> <data>%(user.home)/terracotta/server-data</data> <logs>%(user.home)/terracotta/server-logs</logs> </server> <ha> <mode>networked-active-passive</mode> <networked-active-passive> <election-time>5</election-time> </networked-active-passive> </ha> </servers> </tc:tc-config>
●Terracottaサーバの起動
Windowsの場合とMac/Linuxの場合で起動バッチファイルまたはシェルファイルとなる。
先ほど作成した設定ファイルを使用する場合は、-fオプションで設定ファイルのパスを指定するとよい。
{terracottaのインストールディレクトリ}\bin\start-tc-server.bat (-f tc-config.xml)
{terracottaのインストールディレクトリ}/bin/start-tc-server.sh (-f tc-config.xml)
app.dicon
<component name="cacheManager" class="net.sf.ehcache.CacheManager"> @net.sf.ehcache.CacheManager@getInstance() <destroyMethod name="shutdown" /> </component>
実際にキャッシュに保存、取得するロジックは下記。
public class EhcacheLogic { @Resource protected CacheManager cacheManager; private Cache cache; /** * 初期処理。 */ public void init() { if (!this.cacheManager.cacheExists("terracottaTest")) { this.cacheManager.addCache("terracottaTest"); } cache = cacheManager.getCache("terracottaTest"); } /** * キャッシュに保存する。 * @param key キー値 * @param value 値 */ public void put(String key, String value) { Element element = new Element(key, value); cache.put(element); } /** * キャッシュから取りだす。 * @param key キー値 * @return 値 */ public Object get(String key) { Element element = cache.get(key); if (element == null) { return new String(""); } Serializable originalResult = element.getValue(); return SerializationUtils.clone(originalResult); } /** * キャッシュから削除する。 * @param key キー値 */ public void remove(String key) { cache.remove(key); } }
Terracottaでのクラスタリングは検証中であるが、からり早く各JVMにオブジェクトがコピーされていた。
Terracottaには開発者コンソールというものもある。どのような設定で動作しているのか、また、キャッシュの保存、取得、取得ミスなどの情報が閲覧できる。
調査をすすめて、こちらに追記していきたいと思う。
EhcacheとTerracottaの連携に関して、下記の本を参考にさせていただいた。
- 作者: 西岡祐弥,濱田章吾,横山彰子,浜本階生,ミック,uupaa,塙与志夫,はまちや2,大沢和宏,中島聡,矢野りん,中島拓,浦嶌啓太,角田直行,佐々木一,倉井龍太郎,深町英太郎,岩永賢明,高橋健一,柴田博志,井上誠一郎,大谷弘喜,荻野淳也,原悠,増井俊之,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2011/02/24
- メディア: 大型本
- 購入: 37人 クリック: 2,058回
- この商品を含むブログ (38件) を見る
*1:あるアプリケーションサーバのキャッシュにデータを格納すると他のアプリケーションサーバのキャッシュへデータをレプリケートするキャッシング方式