株式会社ネットワールドのエンジニアがお届けする技術情報ブログです。
各製品のエキスパートたちが旬なトピックをご紹介します。

インメモリコンピューティング -今日までの実装の調査-

本ブログエントリーはPernixData社のプロダクトマネージャであるTodd Mace氏のブログ記事を翻訳しています。 

本記事の原文はIn memory computing - a survey of implementations to dateで閲覧可能です。

ネットワールドのPernixDataに関する情報はこちら。本ブログのPernixDataの記事のまとめはこちら

このシリーズの前の記事ではメモリレーンを散策し、この20~30年でのインメモリコンピューティング(IMC)の進化について復習しました。この記事ではいくつかのIMCの特殊な実装に深く入り込み、今日までに行われてきたイノベーションとその制限について理解していきます。

バッファキャッシュ

バッファキャッシュはページキャッシュと呼ばれることもあります。これはオペレーティングシステムとデータベースに数十年も前から実装されています。バッファキャッシュはディスクアクセスを避けるために頻繁にアクセスされるデータをキャッシュするメモリの一部と説明されます。もちろん、バッファキャッシュを活用することでデータのアクセスがディスクまでいくことを避けられるため、パフォーマンスも大きく向上します。

バッファキャッシュはリードオンリーのキャッシュです。別の言い方をするとバッファキャッシュでメリットを受けられる可能性があるのはリードのためのアクセスだけです。それとは逆に、ライトは常にその下のデータストアに書き込まれなければなりません。これはRAMが揮発性のメディアであり、電源が落ちると、バッファキャッシュに乗っていたデータは永遠に失われてしまうのです。ご想像のとおり、これはデータベースがACIDコンプライアンスに準拠する際に非常に大きなかけになってしまうのです[E:happy01]

以下の図はバッファキャッシュがReadとWrite双方でどのように動作するかを表しています。

Readについては最初のアクセスは必ず下のデータストアに行きますが、2度目以降のアクセスはバッファキャッシュから行われます。

Fig270

Writeについては常に下のデータストアに対して行われます。バッファキャッシュはいかなるメリットも与えることはありません。

Fig271バッファキャッシュがReadだけにしか効果が無いため、非常に限定的です。例えば、OLTPアプリケーションは非常に多くのWrite操作を伴います。これらのWriteは下のデータストアのパフォーマンスに準じるため、殆どの場合、Readがバッファキャッシュから提供されているというメリットを隠してしまうのです。

次に、バッファキャッシュのサイジングもしっかりとしたものがありません。バッファキャッシュのサイズが小さすぎると、メリットは全く得られなくなります。逆にサイズを大きくし過ぎるとそれはメモリの無駄遣いになってしまうのです。もちろん、更に皮肉なことに仮想化環境ではサーバのリソースは仮想マシン間で共有され、インフラストラクチャチームによって管理されています。そうなのです。バッファキャッシュのサイジングはアプリケーション固有の要件で、インフラストラクチャの要件では無いのに、です。結果として、他に同じホストでどんなアプリケーションが動いているのかはわからないまま、そして、どれだけのメモリがサーバで利用できるかということはわからないままこれを行うことになるわけです。

APIベースのインメモリコンピューティング

他にIMCを活用する一般的な方法にアプリケーション内でライブラリやAPIを利用するということが挙げられます。これらのライブラリやAPIによってアプリケーションにメモリをキャッシュとしてつかうことができるようになります。例を挙げるとすればmemcachedでしょう。memcachedがどのようなものかは次に述べます。以下はmemcachedを利用してメモリをキャッシュとして利用するサンプルです。

function get_foo(foo_id)     
foo = memcached_get("foo:" . foo_id)     
return foo if defined foo      
foo = fetch_foo_from_database(foo_id)     
memcached_set("foo:" . foo_id, foo)     
return foo 
end

この例では適切な場所でAPIが呼ばれるようにアプリケーションを書き直しが必要だということを表しています。APIに対する変更やアプリケーションのロジックの変更はすべて書き直しが必要です。

SQLでの類似した例がこちらです。

CREATE TABLE FOO (…..) WITH (MEMORY_OPTIMIZED=ON);

SQLでの例はユーザーとしてどのテーブルがメモリにキャッシュされるべきなのかを指定しなくてはならないということを意味しています。これをテーブルを作成するときに行わなくてはなりません。もしくは、すでに存在しているテーブルであればALTER TABLEコマンドを用います。御存知の通り、DDLの変更にも王道はありません。そればかりか、ユーザーとしてどのテーブルをメモリに保持し、どのテーブルはそうしないかをどうやって決めたら良いのでしょうか?そして、静的なスキーマの定義は今日のような動的な環境で果たしてうまくいくのでしょうか?また、このSQLの拡張はANSI SQLに準拠になるかどうかの保証もないのです。

いずれのケースもIMCを行うために、アプリケーションに根本的な変更を加えなければなりません。これはつまり、必要なAPIをサポートしているデータベースやライブラリに仕方なくアップグレードしなくてはならないということも意味します。そして、最後に、APIの振る舞いが変更されるたびにアプリケーションをいじらないといけないということも意味しています。

インメモリアプライアンス

最近では、ISVが彼らのアプリケーションをメモリ上で動作させているアプライアンスを販売していることもあります。巨大なDRAMを搭載できるサーバが一般的になってきたことから、このタイミングは理にかなっています。これらのアプリケーションは基本的にはRAMをリードオンリーのキャッシュとして利用します。バッファキャッシュのところでお話したとおりで、リードオンリーキャッシュには制限があります。

さらに、多くのアプリケーションはデータベースをACID準拠で動作させており、一貫性が主要件です。これはつまり、一貫性を保証するために、Writeは不揮発性のメディアに書き込まれなければならないということを意味しています。システム内にWriteが多く発生すると、パフォーマンスはRAMではなく、不揮発性のメディアに準じてしまいます。機械式のドライブではなく、Flashを利用することである程度はこれを緩和することができますが、インメモリコンピューティングのためのアプライアンスを買おうとしている人が、Flashのパフォーマンスしか保証されないということは不幸なことに見えます。

ほとんどのアプリケーションは非常に長い起動時間があります。大抵はデータを起動時にRAMにデータをキャッシュとして読み込みます。「オンデマンド」ではなく、データをRAMに事前に読み込んでしまうアプローチです。これはデータのサイズが非常に大きい場合に起動時間は非常に長くなってしまうということを意味しています。

最後に、運用の面から特定の目的のためだけのアプライアンスを利用するということは更にサイロを増やし、特殊な監視や管理を行うということを意味します。これは仮想化によってもたらされた素晴らしい価値を取り払ってしまうことにつながります。

まとめ

今日のIMCはエンドユーザーやアプリケーションオーナーがストレージのパフォーマンスを改善するために提供されています。しかし、問題はインフラストラクチャの中にあるのです。結果として局所的なプロプライエタリの最適化を行うことで、インフラストラクチャを最適に使うことができなくない、もしくは全てが上手く行かなくなるということが起こります。インメモリコンピューティングでストレージのパフォーマンスの問題をインフラストラクチャレベルでちゃんと解決する正しい方法は無いのでしょうか?結局のところ、ストレージパフォーマンスはインフラストラクチャのサービスなのです。詳しくは http://www.pernixdata.com(日本語版は http://www.networld.co.jp/pernixdata/) をご参照ください。

記事担当者: マーケティング本部 三好哲生 (@pernixdata_netw)