Кэш Yii2 показывает старые данные: как искать причину

Кэш в Yii2 помогает ускорить сайт, но иногда становится причиной путаницы. В админке данные изменили, а на публичной странице всё ещё старая цена. Категорию переименовали, но меню не обновилось. Таблицу изменили миграцией, а приложение продолжает считать, что колонки нет.

В таких случаях важно понять, какой именно кэш мешает: файловый, Redis, fragment cache, data cache, schema cache, assets или даже браузерный кэш.

Сначала определить симптом

Разные симптомы ведут к разным видам кэша.

  • старый текст на странице — fragment cache или data cache;
  • старая структура таблицы — schema cache;
  • старые стили и скрипты — assets или browser cache;
  • старое меню — кэш выборки или виджета;
  • разные данные у разных пользователей — возможно, кэш зависит от роли или сессии.

Если после очистки всего кэша проблема пропадает, это не финальное решение. Нужно найти место, где кэш должен сбрасываться точечно.

Очистка всего кэша

Для быстрой проверки можно выполнить стандартную команду Yii2:

php yii cache/flush-all

Если используется несколько компонентов кэша, стоит проверить конфиг. Например, cache может быть файловым, а отдельный компонент redisCache — Redis.

'cache' => [
    'class' => 'yii\caching\FileCache',
],

'redisCache' => [
    'class' => 'yii\redis\Cache',
],

Файловый кэш

FileCache обычно хранится в runtime/cache. При ручной очистке лучше удалять содержимое, а не саму директорию.

rm -rf runtime/cache/*

После удаления нужно убедиться, что приложение может снова писать в runtime.

ls -la runtime
ls -la runtime/cache

Redis

Если кэш в Redis, очистка файлов ничего не даст. Нужно смотреть настройки подключения и выбранную базу Redis.

redis-cli -n 0 keys "*"

Команда keys на больших Redis-базах может быть тяжёлой. На production лучше использовать scan или штатные команды приложения. Полный flushdb опасен, если в Redis лежат не только кэш сайта, но и очереди, сессии или данные других проектов.

Fragment cache

В представлениях Yii2 часто встречается кэширование фрагмента. Если нет зависимости, фрагмент будет жить заданное время и не узнает, что данные изменились.

<?php if ($this->beginCache('main-menu', ['duration' => 3600])): ?>
    <?= $this->render('_menu') ?>
<?php $this->endCache(); endif; ?>

Для данных, которые меняются из админки, лучше использовать зависимость.

use yii\caching\TagDependency;

<?php if ($this->beginCache('main-menu', [
    'duration' => 3600,
    'dependency' => new TagDependency(['tags' => 'menu']),
])): ?>
    <?= $this->render('_menu') ?>
<?php $this->endCache(); endif; ?>

После изменения меню можно сбросить тег:

TagDependency::invalidate(Yii::$app->cache, 'menu');

Data cache

Если данные кэшируются вручную, нужно проверить ключ и условия сброса.

$key = ['category-tree'];

$tree = Yii::$app->cache->get($key);
if ($tree === false) {
    $tree = Category::find()
        ->where(['active' => 1])
        ->orderBy(['sort_order' => SORT_ASC])
        ->asArray()
        ->all();

    Yii::$app->cache->set($key, $tree, 3600);
}

Если при сохранении категории этот ключ не удаляется, пользователь будет видеть старое дерево до истечения TTL.

Yii::$app->cache->delete(['category-tree']);

Schema cache

После миграции Yii2 может не сразу увидеть новую колонку, если включён schema cache. Тогда в логах бывают ошибки вида Unknown Property или неизвестная колонка в модели.

php yii cache/flush-schema

Или полная очистка кэша:

php yii cache/flush-all

Assets и браузер

Старые CSS и JS — это отдельная история. Yii2 публикует assets в web/assets, а браузер может кэшировать файлы по URL.

rm -rf web/assets/*

Для статики полезно включить версионирование:

'assetManager' => [
    'appendTimestamp' => true,
],

Чек-лист диагностики

  1. Понять, какие именно данные устарели.
  2. Выполнить cache/flush-all для проверки гипотезы.
  3. Проверить компонент cache в конфиге.
  4. Проверить fragment cache в представлениях.
  5. Проверить ручные cache->get и cache->set в коде.
  6. Проверить schema cache после миграций.
  7. Проверить Redis, если он используется.
  8. Добавить точечный сброс через delete или TagDependency.

Кэш должен ускорять сайт, а не делать данные непредсказуемыми. Если после каждого изменения приходится вручную чистить всё, значит в проекте не хватает точечной инвалидации. Это лучше исправить один раз, чем постоянно лечить симптом.

Комментарии (0)

Пока нет комментариев. Будьте первым!