もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

laravelのcachedriverをmemcachedにしている状態で ttlを指定してもなぜか時間が来てもデータが消えない

はじめに

こんばんは。

今日作業しているときにぶち当たった謎がありました。

もう解決済みですが、備忘録として残しておきます。

laravelのcache_driverを memcached に設定している状態で ttlを指定して保存したが、なぜか期限が切れてもデータが消えませんでした。

laravel.com

本題

実際に使用しているコードは以下

$key = 'xxxx_key';
$value = 'aaaaaa';
$ttl = 3600;
Cache::put($key, $value, $ttl);

ドキュメントにも書いている書き方で、全く問題ないと思ってました。

ただ、ttlで設定していた1時間がたってもデータが消えず Cache::get($key) で取れてしまうという謎の状態が続きました。

実際に処理がどうなっているかを確認してみたところ 以下のようなコードでした。

Illuminate\Cache\MemcachedStore.php

    public function put($key, $value, $seconds)
    {
        return $this->memcached->set(
            $this->prefix.$key, $value, $this->calculateExpiration($seconds)
        );
    }

    protected function calculateExpiration($seconds)
    {
        return $this->toTimestamp($seconds);
    }

    protected function toTimestamp($seconds)
    {
        return $seconds > 0 ? $this->availableAt($seconds) : 0;
    }

availableAt($seconds)MemcachedStore がuseしているtraitが本体です。

それが以下。

Illuminate\Support\InteractsWithTime.php

    protected function availableAt($delay = 0)
    {
        $delay = $this->parseDateInterval($delay);

        return $delay instanceof DateTimeInterface
                            ? $delay->getTimestamp()
                            : Carbon::now()->addRealSeconds($delay)->getTimestamp();
    }

ということで最終的にmemcachedを保存する際にはttlはtimestampで保存されるようです。

3600という秒数が保存されると思っていたので、ちょっと予想とは違いましたが、まぁ問題ないはずだと思っていました。

うーんうーん。と唸って色々確認していたところ、やっと問題がわかりました。

dockerで作成していた memcachedコンテナのTZが UTC になっていることが問題そうでした。

application側は JST なので JST の状態でtimestampを送ることになるが、 memcached側は UTCなので9時間プラスされたttlになっているという事だったようです。

コードは特に問題なく、インフラ側の問題でした。

終わりに

なかなかハマっちゃいました...

現場からは以上です。