ちょうど今、珍しく私の住んでいる地域に台風が直撃しているようです。
みなさんもくれぐれもお気をつけ下さいね。
さてさて、今回は数日前にリニューアル公開したインフォブログランキングの作業中に起こった「Laravelのキャッシュが消えない現象」についてご紹介しようと思います。
(はい。最近Laravel漬けになっています。知れば知るほど「すごいなー」とつぶやいています^^)
[最終結論: バグではないけど、別の仕様を追加してほしい]
まず、私に起こった問題は以下のようなものでした。
日付が変わると新しいデータをDBから取得して、それをまたキャッシュとして保存する。
↓↓↓
でもキャッシュが削除されず同じデータのまま。
つまり、その日ごとにデータを表示したかったのでその都度DBにアクセスをせずキャッシュを利用した、ということです。
実際のプログラムは以下。
if(Cache::has('key')) {
return Cache::get('key');
}
// DBからデータを取得
$dt = Carbon::tomorrow(); // 明日の日付を取得
Cache::put('key', $value, $dt);
return $value;
※前回紹介したCarbonを使っています。
※現在はより便利なCache::remember() を使っています。
一見問題なさそうなのですが、、、?
実はこれではキャッシュが消えなくなる(可能性を持っている)のです。
なぜなら、元々Laravelのキャッシュの有効期限はタイムスタンプではなく、「分」を使っているから
なのです。
つまり、上の例でいうと、
1.Laravelは、$dt を使って明日が始まる時間まで何分かを取得。
2.その分数を有効期限とするキャッシュを作成
???
やっぱり問題ないのでは、、、?
これが大有りなんです。
なぜなら、Carbon(dateTime)から分を取得するとき intval() で数字が切り下げになってしまう
のです。
そう!
つまり、キャッシュはまだ日付が変わっていないのに有効期限が切れて削除され、そしてその当日のデータ(すでに保存されているものと同じデータ)をまた新しく保存してしまうというものです。
インフォブログランキングは手前味噌ですが、なかなかページビューが多いサイトなのでこの僅かな時間に新しいアクセスがあり、キャッシュがうまく更新されていないという状況でした。
???
でも、新しいキャッシュができたとしてもまた、明日までの有効期限だからすぐに新しいデータに置き換わるのでは???
実は、これもそうでもないんです。
結論からいうと、
分数がゼロの時はキャッシュは永遠に保存されてしまう
からなのです。
つまり、分がintval()で切り下げられてキャッシュを保存し、そのキャッシュが削除ときには残り時間は予定の時間まで1分未満になります。
その1分未満はintval() でゼロに変換されてキャッシュが消えない状態になってしまうということですね。
ということで、
※おそらく間違いはないと思っていますが、自信がない部分もありますのでこの記事に修正が必要でしたらぜひ教えてください。よろしくお願いいたします。m_ _m
ではでは〜。
0 件のコメント:
コメントを投稿