mixi engineer blog

*** 引っ越しました。最新の情報はこちら → https://medium.com/mixi-developers *** ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

memcached-1.4 RCをつかってみよう

数日前にmemcached-1.4のリリース候補が出ましたので、今日はその最新版と、それを使ったメモリ節約の運用法を紹介します。厳密にいうと、ご紹介させていただくmemcachedのメモリ節約機能は1.3のbetaから存在し、過去にこちらで取り上げました

memcached-1.4.0-rc1

1.4 RCは基本的に1.3.* betaで発見・報告されたバグの修正やコードベースの改修が主な内容です。詳しいリリースノートはこちらになります。 ダウンロードはこちらです。

新しいバージョンのmemcachedはバイナリプロトコルの導入以外に地味に生まれ変わっています。例えばコードベースを時代の流れにあわせて、シングルスレッドサーバのビルドをとり除いたり、過去から問題視されていたグローバルロックたちの一つを排除し、SMPパフォーマンスを向上させたことなどです。また、このエントリーの本題であるmixiにとって嬉しい新機能も登場しましたので、それを次に紹介します。

CASを使わない人はメモリを節約しよう

memcachedにはCASをエミュレートした機能が存在し、CASの値を64ビット整数で表現しています。この値は今まではレコードを表現する構造体のメンバーとして記録されていました。現在はこのデータをダイナミックにメモリ上でアラインできるようになっています。したがって、CASを使わない設定 (-C オプション) でmemcachedを起動すると、1レコードに対して8バイトのデータを節約する事ができます。

1レコードにつき8バイトの節約と聞くと大した数字に聞こえないかもしれませんが、たったの1000万レコードでおよそ76MBのメモリ空間を節約する事ができます。この機能によるインパクトはウェブサービスの様に粒度の細かなキャッシュを多数つくるユースケースでは言うまでもなく大きいです。弊社でも検証してみたところ、嬉しい結果を得る事ができました。

余談ですが、この節約機能はもともと開発のロードマップには載っておらず、Wikipediaの中のパフォーマンス屋さんの要望で実現されました。

簡単な検証

私のブログで使った例と同じで恐縮ですが、まず10万個のKey/Valueをキャッシュする簡単なスクリプトを用意します。
#!/usr/bin/perl

use strict;
use warnings;

use Cache::Memcached;
use constant {
    NITEMS => 100000,
    KLEN   => 8,
    VLEN   => 16,
};

sub random_key {
    my @chars = ('a'..'z', 'A'..'Z', '0'..'9');
    my $buf = "";

    foreach (1..KLEN) {
        $buf .= $chars[rand @chars];
    }
    return $buf;
}

my $memc = Cache::Memcached->new ({
    servers => ['localhost:11211'],
    debug   => 0,
});

my $val = 'a' x VLEN;

for (1..NITEMS) {
    $memc->set(random_key, $val);
}

そしてこのスクリプトを新機能を適用していない以下のオプションで起動したmemcachedのプロセスに対して行います。

$ memcached -m 1024

そして以下がstatsコマンド(一部)の結果です。

...
STAT bytes 9000000
STAT curr_items 100000
STAT total_items 100000
STAT evictions 0
END

さて、次に新しいメモリ節約オプションを有効にしたサーバに同じスクリプトを走らせます。

memcached -m 1024 -C

そして結果です。

...
STAT bytes 8200000
STAT curr_items 100000
STAT total_items 100000
STAT evictions 0
END

ご覧のとおり、781KBのメモリを節約したことがわかります。これだけのメモリをさらにキャッシュにつかえるので、インフラのコストパフォーマンスが向上し、ウェブサービス屋さんにとって嬉しい機能であることがわかっていただけるかと思います。

まとめ

memcached-1.4.0-rc1と新しいオプションを紹介しました。メモリ節約オプションを有効にすると一つのキャッシュレコードに対して、8バイトのメモリ領域を節約することができ、塵も積もれば山となる論理で、結果的にインパクトのあるメモリ空間の節約になります。

このRCには開発者たちだけではなく、様々な人たちや組織のフィードバックがこめられているので、ぜひ試していただけたらなと思います。