LoginSignup
0
0

More than 3 years have passed since last update.

memcachedをflushしたあと最大1秒間データは追加できなくなる

Posted at

はじめに

古いPHPのコードのテストでmemcacheのflushまわりで変な挙動をしているので調べていたのですが、PHPのMemcache::flushのマニュアルのUser Contributed Notesに気になる記述を見つけました。

Please note that after flushing, you have to wait a certain amount of time (in my case < 1s) to be able to write to Memcached again. If you don't, Memcached::set() will return 1, although your data is in fact not saved.

flushしたあと1秒待たないと、setが成功するけど実際にはデータが保存されないと言っているのですが、ソースを見たら本当にそうだったので仕組みを説明します。

仕組み

memcached の expire の仕組みはアイテムごとに期限を持っていて、データを取り出すときに期限が現在時刻より過去なら期限切れ判定してデータを開放する、という感じだというのはうっすらと知っていたのですが、flushのために追加で以下のようなことをしています。

  • flushを実行すると、この時刻までのタイムスタンプを持っているアイテムはflushされたと判定するよというsettings.oldest_liveに現在の時刻(+与えられていればオフセット)を設定します。

  • itemがflushされたか判定する関数item_is_flushed()ではitemのタイムスタンプ <= settings.oldest_live ならflushされていると判定します

int item_is_flushed(item *it) {
    rel_time_t oldest_live = settings.oldest_live;
    uint64_t cas = ITEM_get_cas(it);
    uint64_t oldest_cas = settings.oldest_cas;
    if (oldest_live == 0 || oldest_live > current_time)
        return 0;
    if ((it->time <= oldest_live)
            || (oldest_cas != 0 && cas != 0 && cas < oldest_cas)) {
        return 1;
    }
    return 0;
}

時刻の精度は秒なので、flushを実行したのと同じ秒の間は新しいアイテムを追加してもタイムスタンプが同じになるのでflushされたアイテムであるという判定になってしまいます。これがデータが保存されない仕組みです。(正確には保存されるけどflushされていると扱われるので取り出すことができません)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0