はじめに
こんばんは。
今日作業しているときにぶち当たった謎がありました。
もう解決済みですが、備忘録として残しておきます。
laravelのcache_driverを memcached に設定している状態で ttlを指定して保存したが、なぜか期限が切れてもデータが消えませんでした。
本題
実際に使用しているコードは以下
$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になっているという事だったようです。
コードは特に問題なく、インフラ側の問題でした。
終わりに
なかなかハマっちゃいました...
現場からは以上です。