読者です 読者をやめる 読者になる 読者になる

mixi engineer blog

ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

memcachedのストレージ層をmodularにしてみた

mixi

前回に続いてまたmemcachedの話をしたいと思います。今回は改造編です。

ハッシュデータベースサーバなどの実装でmemcachedライクなものを書くのも良いですが、以前からmemcached自体のストレージをmodularにできたら面白いかも?と思っていたので実験的にmemcachedを改造してみました(memcached-1.2.4がベース)。

とりあえず名前はmemcached modularの略でmmcmodと名づけて、mikioさんのTokyo Cabinetをストレージとして使うモジュール(厳密にいうと共有ライブラリ)を書きました。ソースコードは後日CodeReposの方に上げますがとりあえずこの記事で公開します。ちなみに新しいプロダクトを作る気はなくて、最終的にpatchを作ることが目的です。

で、話を続けると今回の改造を簡単にビジュアライズするとこんな感じです:

memcached modular

図のmmcstorageは外部ライブラリとリンクしてサーバ内でストレージエンジンの様に使用される更なるラッパーです。

ソースコード

mmcmod:

TokyoCabinetのハッシュデータベースモジュール:

ビルドは通常通りアーカイブの展開後にディレクトリに入って:

./configure
make
make install

で行います。

mmctchdbをビルドするには予めTokyo Cabinetのインストールが必要で、mmcmodをビルドするにはmemcachedと同じく予めlibeventのインストールが必要です。

mmcmodの使い方

"-e /path/to/library" でモジュールを指定します。モジュールを指定しなかった場合は通常のmemcachedとして起動します。

"-o filename"で出力データベースファイルの名前を指定できます、指定しなかった場合はmmcmod.dbというデータベースファイルが作成されます。

例えばmmctchdbがデフォルトのパスにインストールされていたら:

mmcmod -e /usr/local/lib/mmctchdb.so -o mystorage.db

mystorage.dbという名前のTokyo Cabinetのハッシュデータベースがストレージとして使われます。ただし、デーモンとしてmmcmodを起動する場合は必ず絶対パスで許可のある場所にファイルを作るよう指定してください。

使ってみた結果

上記の方法でmmcmodを起動して前回の記事で書いたmemstormで以下の様に:

memstorm -s tokyo -n 10000 -k 32 -l 64

実行してみたところ:

----
Num of Records      : 10000
Non-Blocking IO     : 0
TCP No-Delay        : 0

Successful   [SET]  : 10000
Failed       [SET]  : 0
Total Time   [SET]  : 2.39497s
Average Time [SET]  : 0.00024s

Successful   [GET]  : 10000
Failed       [GET]  : 0
Total Time   [GET]  : 2.50545s
Average Time [GET]  : 0.00025s
----

という結果が返ってきました。 ここで気になるのが本当の本当にTokyo Cabinetにデータが保存されているのか?という事ですよね。という事でTokyo Cabinetのユーティリティツールでデータベースファイルを見てみたところレコードは挿入されています:

[]$ tchmgr inform mystorage.db

path: mystorage.db
database type: hash
additional flags:
bucket number: 16381
alignment: 16
free block pool: 1024
options:
record number: 10000
file size: 1989952

他にも動作確認を行いたかったのでCache::Memcached::Fastのmake testを実行させてみたところ、とりあえずテストは通過する事ができました。

ちなみにmemcachedとして(ライブラリを指定しないで起動)だと:

----
Num of Records      : 10000
Non-Blocking IO     : 0
TCP No-Delay        : 0

Successful   [SET]  : 10000
Failed       [SET]  : 0
Total Time   [SET]  : 2.38709s
Average Time [SET]  : 0.00024s

Successful   [GET]  : 10000
Failed       [GET]  : 0
Total Time   [GET]  : 2.51502s
Average Time [GET]  : 0.00025s
----

という結果になりました。

ここで面白いのがメモリ上で済む程度のデータ量でしかテストを実行していないとはいえ、Tokyo Cabinetのハッシュデータベースではmemcachedのメモリストレージと同等、もしくはより高速なパフォーマンスの可能性が見られるという事です。この驚異的なパフォーマンスに驚かずにはいれませんね。

Modularだと何が嬉しいか

まず第一にメモリという限られたリソースに捕らわれずに高速に大量のデータを扱う事が可能です。しかもストレージがデータベースであればデータを永続的に保持することが可能です。ちなみにmodularではないですが既存のプロダクトでWikimediaが作ったTugela CacheというBerkeley DBをストレージとして使うものがあります。

運用上のメリットを述べるとmemcachedを既に使っているシステムはクライエントサイドを大改造しなくても比較的楽にバックエンドの交換が可能な事です。しかも色々な言語で書かれた素敵なクライエントライブラリが既に世の中に存在しているのでこれらを取り込めるメリットもあります。

もう一つボーナス的な事は保存先が特定のものに特化しないという事です。ライブラリの実装は基本仕様さえ守れば自由なので、典型的な"memcachedに入ってなかったらRDBMSからデータを取る"という処理を全て抽象できます。又、ストレージがハッシュデータベースでなくてもストレージとして使用する事ができます。例えばAmazon S3のようなサービスに送る事だってやろうと思えば可能です。

注意書き

mmcmodはまだ実験段階でUDPとマルチスレッドモードに対応していない事と、今のところ以下のオペレーションしか対応していません:

  • ADD
  • REPLACE
  • SET
  • GET
  • INCR
  • DECR
  • DELETE

追々append,prepend,flush,statsを対応する予定です。

まとめ

今回は実験的に開発したmmcmodというmemcachedのストレージ層をmodularにしたキャッシュ兼ストレージサーバを紹介しました。私のような未熟者が書いた拡張なのでまだまだ完成には程遠いですが個人的に面白いと感じるプログラムなので継続して開発しようと思います。