1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelのデータベースキャッシュドライバは、期限切れのキャッシュを自動的に削除しない

Last updated at Posted at 2024-11-10

概要
有効期限切れのキャッシュのレコードは自動的には削除されません。
取得時(getメソッド)に有効期限切れかチェックされ、有効期限が切れていれば削除されます。
https://stackoverflow.com/questions/38250191/when-does-laravel-clear-the-cache

背景

Laravelでデータベースキャッシュドライバを使用して、10s後に期限切れになるキャッシュを作成しました。

Cache::put('key', 'value', $seconds = 10);

cacheテーブルに以下のレコードが追加されました

key value expiration
key s:5:"value"; 1731198618

しかし、10s後になってもレコードは残っていてdocにもそのような記載が見当たらない為調査しました。

データベースキャッシュドライバは、期限切れのエントリを自動的に削除しない

こちらに記載されていました。

今回はLaravel 8.3を使っています。
最新だとこちらです

vendor/laravel/framework/src/Illuminate/Cache/DatabaseStore.php
/**
     * Retrieve an item from the cache by key.
     *
     * @param  string  $key
     * @return mixed
     */
    public function get($key)
    {
        return $this->many([$key])[$key];
    }

    /**
     * Retrieve multiple items from the cache by key.
     *
     * Items not found in the cache will have a null value.
     *
     * @return array
     */
    public function many(array $keys)
    {
        if (count($keys) === 0) {
            return [];
        }

        $results = array_fill_keys($keys, null);

        // First we will retrieve all of the items from the cache using their keys and
        // the prefix value. Then we will need to iterate through each of the items
        // and convert them to an object when they are currently in array format.
        $values = $this->table()
            ->whereIn('key', array_map(function ($key) {
                return $this->prefix.$key;
            }, $keys))
            ->get()
            ->map(function ($value) {
                return is_array($value) ? (object) $value : $value;
            });

        $currentTime = $this->currentTime();

        // If this cache expiration date is past the current time, we will remove this
        // item from the cache. Then we will return a null value since the cache is
        // expired. We will use "Carbon" to make this comparison with the column.
        [$values, $expired] = $values->partition(function ($cache) use ($currentTime) {
            return $cache->expiration > $currentTime;
        });

        if ($expired->isNotEmpty()) {
            $this->forgetManyIfExpired($expired->pluck('key')->all(), prefixed: true);
        }

        return Arr::map($results, function ($value, $key) use ($values) {
            if ($cache = $values->firstWhere('key', $this->prefix.$key)) {
                return $this->unserialize($cache->value);
            }

            return $value;
        });
    }

期限切れのキャッシュは、取得時(getメソッド)にチェックされ、期限が切れていれば削除されます。
キャッシュのクリーンアップは、明示的にforgetやflushメソッドを呼び出す必要があります。

試しにgetで取得し、その後レコードがcacheテーブルから消えていることを確認します。

Cache::get('key');

確認した所レコードは確かに消えていました。

最後に

期限切れになったら消えると思っていたので勉強になりました。

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?