バージョン 4.0.24 のリリースによって,Caucho のアプリケーションサーバ Resin のキャッシュ機構はクライアントとサーバ両方の memcached インターフェースを提供するようになった。つまり memcached ソリューションを代替可能な機能を持ったということだ。サーバとクライアントともに Resin を使用する場合,キャッシュサーバの追加と削除は自動的にクライアントに反映され,再スケーリングや更新が行われる。Resin のキャッシュ機構は Java で実装されているが,パフォーマンス向上のため部分的に JNI を使用している。
Memcached は汎用目的の分散メモリキャッシュシステムだ。C言語で実装されたオリジナル版は元々,Danga Interactive が LiveJournal のために開発したものだったが,現在では YouTube や Reddit,Facebook,Twitter など多数のサイトで採用されている。システムはクライアントサーバ・アーキテクチャを採用している。サーバが管理するキー・バリュー形式の連想配列に,クライアントがデータ追加や照会を行う形式だ。最大 250 バイトのキーに対して,1メガバイトまでのデータを格納することができる。標準的な memcached 実装では,サーバ上のデータはメモリ上に保持されていて,メモリを使い切ると最も古いデータから順に破棄される。しかし Resin の取ったアプローチはこれとは少し違う。InfoQ では Resin 版 memcached 実装のリードアーキテクトである Scott Ferguson 氏に,その詳細について話を聞いた。
InfoQ: memcached との互換性は,どのような方法で確認されているのでしょう? memcached の機能の中で未実装のものはありますか?
Memcached の通信プロトコルは公開されていています。Resin の memcached はそれを実装したものです。
テストは memcached クライアントを対象に実施しました。現時点ですべての memcached 機能をサポートしています。つまり Resin は,memcached ソリューションを置き換え可能であるということです。Resin の memcached サポートは堅牢で高い柔軟性を備えています。データベースに影響を与えることなく,必要に応じてノードの追加や削除が可能です。
InfoQ: 標準的な memcached ライブラリと比較して,パフォーマンス面ではどうでしょうか?
公式なベンチマークは発表していませんが,社内で行ったベンチマークでは,いくつかのユースケースではやや高速,その他のユースケースでは5%以内という結果が出ています。パフォーマンスは高いと思います。読み取り優先でキャッシュを使用するならば, 標準的な memcached の機能に加えて,柔軟性と永続性という利点があることになります。
InfoQ: ブログの記事には "データは自動的に永続化され,Tirad ハブサーバ間で複製される。キャッシュサイズは,ホスト OS 上のハードディスクサイズによってのみ制限を受ける。" とあるのですが,ディスクへの永続化はパフォーマンス特性に大きく影響するのではないのでしょうか?
確かに,データがメモリから参照される場合の速度は同じですが,ディスクから参照される場合は遅くなります。すべてのデータを保持するために十分な大きさの RAM を設定すれば,パフォーマンスは memcached と同じになります。しかしそうでない場合は,それでもデータベースを参照するよりは断然早いのですが,おそらく Membase と同じ程度になると思います。ただしキャッシュの頻繁にアクセスされる部分はメモリ上に残る,ということを考慮に入れれば,オーバーヘッドはごく低いものと考えられます。ユースケースや設定の内容にもよりますが,memcached と同程度のパフォーマンスは期待できます。一方で,ストレージにメモリの制限はありませんし,memcached ノードを追加しても RDBM サーバへのアクセスが過大にならないような柔軟性も備えています。これらは大きな利点です。 Resin の memcached は適応力が高く,クラウド環境でのセットアップも容易です。Resin にも同梱されています。設定も利用も簡単です。
InfoQ: 動作上の相違はないのでしょうか? 例えば memcached の動作を前提に作成されたコードでは,古い内容が破棄されることを期待して,キャッシュの削除を行っていないかも知れません。その場合,キャッシュが無制限に拡大してしまうようなことはないのでしょうか?
ありません。キャッシュ上の項目には期限があるからです。memcached と同じように,有効期限を設定することができるのです。実際に破棄されるのは後になるかも知れませんが,動作としては同じです。JCache (私たちは JSR 107 に密接に関わっています) インターフェースも提供しているので,無期限キャッシュに設定したり,キャッシュの細やかな制御と設定を行うことも可能です。さらに JCache を使用する場合には,GC レスのインメモリキャッシュが実装されています。項目が第1レベルキャッシュのある場合,パフォーマンスは memcached 層を参照するよりも 1000倍高速になります。memcached 層によるバックアップとインメモリの速度を利用するには,これが簡単なセットアップ方法です。
Scott Ferguson 氏の言うように,Resin の memcached のクライアント API は JSR 107,すなわちメモリキャッシュ用の Java インターフェース標準として提案中の JCache (javax,cache) を基本にしている。 設定したキャッシュは,他の CDI オブジェクトと同じ方法でインジェクト可能だ。
import javax.inject.*;
import javax.cache.*;
public class MyBean {
@Inject Cache _memcache;
}
Resin を memcached サーバとして設定するには,以下のような <listen> タグを追加すればよい。
<resin xmlns="http://caucho.com.ns/resin" xmlns:memcache="urn:java:com.caucho.memcache"> <cluster id="cache_tier"> <server-multi id-prefix="cache-" address-list="${cache_tier}" port="6820"> <listen port="${rvar('memcache_port')?:11212}" keepalive-timeout="600s" socket-timeout="600s"> <memcache:MemcacheProtocol/> </listen> </server-multi> </cluster> </resin>