Erlang(Mnesia) で memcached (互換なし)を作ってみました

DSAS開発者の部屋:Erlang で memcached を作ってみました。
触発されました。で、家族サービスを一日サボって作りました。嫁と子供達に感謝!

http://labs.miu.vc/svn/cooldaemon/erl/yamd/trunk/

memcached との違い

  • プロトコル(w;
  • validation が抜けまくりなので、虐めると速攻で落ちる

急いで作ったので、いろいろイケてませんが、そのうち直して、自分の所のプロダクト環境で使う予定です。
将来的には、ssl 通信、ユーザ・ホスト認証、バックアップ、監視、他の erlang node を勝手に memcached にする機能なんかも加える予定です。
気が向けば、memcached 互換も検討します。

DSAS の中の人が作ったのとの違い

  • memcached 互換じゃない
  • ベンチマークを調べていない
  • Mnesia を使ってる
  • memcached みたいに、normal set replace に対応している
  • expire の処理は専用プロセスに任せている
  • 微妙に OTP っぽい
  • 慣れ親しんだコマンドラインから操作可能

使い方

% svn co http://labs.miu.vc/svn/cooldaemon/erl/yamd/trunk/ yamd
% cd yamd
% make
% scripts/yamd.sh start

これで、11211 を Listen します。
scripts/yamd.sh stop で停止できます。

% telnet localhost 11211
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to miu.vc.
Escape character is '^]'.
set normal aaa 0 5
aaaaa
SUCCESS
get aaa
SUCCESS aaa 5
aaaaa
delete aaa
SUCCESS
get aaa
FAILURE aaa
no exists
quit
Connection closed by foreign host.

set の normal の箇所には add や replace が指定できます。
始めの 0 が expire で、5 がデータのサイズです。
後で、validation を入れてマニュアル書こう…。

DSAS の中の人が作った source を見て

そこで通常は line モードでコマンドを受信しますが、set コマンドを受け取ったら raw モードに切り替え、バイナリデータを受信したら line モードに戻す様なコードになっています。

もう天才かと。
早速、パクらさせて頂きました。多謝!

ちなみに、下記のコードには誤りがあります。

epoch() ->
    {Msec, Sec, _} = now(),
    Msec * 1000 + Sec.

now() は、{MegaSec, Sec, MicroSec} なので 1000 ではなく 1000000 を掛ける必要があります。

気になる箇所

qlc:q([
  X#store.value || X <- mnesia:table(store),
  X#store.key =:= Key,
  timer:now_diff(X#store.expire, T) > 0 orelse X#store.expire =:= ?UNLIMITED
])

こんな書き方していると expire に索引を付けても、索引が使われないのではないだろうか?
qlc よく解らない…。

名前空間memcached の flag に対応。I/F だけ弄れば memcached 互換にもできる。次はレプリだな。