サーバのセッション管理にmemcachedを使ってたのですが
サーバが落ちたらセッション全部消えてしまうことから
repcachedを使ってレプリケーションをすることにしました。
そうするとmemcachedに乗ってるデータをrepcachedに移し変えなければならないため、
memcached-toolを使ってDUMPし、データをインポートしました。
その際、有効期限が無期限のデータが消えるという事象に遭遇したため、そのメモです。
Dumpにはこのツールを利用させてもらうことにしました。
memcached-tool
https://github.com/memcached/memcached/blob/master/scripts/memcached-tool
使い方は以下のような形です。
# memcachedのデータをダンプ
memcached-tool localhost:11211 dump > 11211.dump
# インポートする時
cat 11211.dump | nc localhost 11211
しかし前述したように使ってみるとちょっとした問題が発生しました。
memcachedの中に有効期限が無期限で設定されていたデータがあったのですが、
それらがインポートしたときにすべて消えていました。
よくよく調べてみると、memcachedは有効期限を0に設定したデータを入れたとき、
内部的にはmemcached起動時のタイムスタンプで設定されているようです。
それがそのままmemcached-toolで出力されたため、
有効期限が過去の値で設定されてしまい、
入れるそばから消されるというなんとも残念な挙動をしていました。
(memcachedはgetしたときに有効期限が切れていると削除するため正確な表現ではないですが)
そこでこのmemcached-toolを少し修正して無期限のデータに対応しました。
83行目あたりでstats itemsを投げていますが、
その前にmemcachedの起動してからの時間と
statsコマンドを投げた瞬間のタイムスタンプを取得しておきます。
(これらを使って運用中のmemcachedがいつ起動されたのかを判定します)
# get uptime
print $sock "stats\r\n";
my $uptime;
my $time;
while (<$sock>) {
last if /^END/;
if (/^STAT uptime (\d*)/) {
$uptime = $1;
}
if (/^STAT time (\d*)/) {
$time = $1;
}
}
my $started_at = ($time - $uptime);
そして117行目あたりで作っているaddコマンドを変更します。
my $exptime = $keyexp{$k} != $started_at ? $keyexp{$k} : 0;
#print "add $k $flags $keyexp{$k} $len\r\n$val\r\n";
print "add $k $flags $exptime $len\r\n$val\r\n";
こんな感じで有効期限が0でsetされているデータを拾い上げました。