LaravelSeniorSystem design
Как работает кэширование в Laravel? Какие cache drivers доступны?
Laravel Cache работает через единый фасад Cache с поддержкой драйверов file, database, redis, memcached, dynamodb, array и null. Конфигурация в config/cache.php, переключение через .env CACHE_STORE.
Архитектура кэширования в Laravel
Laravel реализует кэш через контракт Illuminate\Contracts\Cache\Repository и фасад Cache. Все обращения идут через единый API вне зависимости от выбранного хранилища. Настройки находятся в config/cache.php, активный драйвер задаётся переменной CACHE_STORE в .env.
Доступные cache drivers
- file — хранит данные в файлах внутри
storage/framework/cache. Подходит для разработки и небольших проектов. Не работает в multi-server окружении без общего NFS. - database — таблица
cacheв БД. Создаётся командойphp artisan make:cache-table && php artisan migrate. Медленнее Redis, но не требует дополнительной инфраструктуры. - redis — рекомендуемый вариант для production. Настраивается в
config/database.phpсекцияredis, требует пакетpredis/predisили PHP-расширениеphpredis. - memcached — требует PHP-расширение
memcachedи пакетext-memcached. - dynamodb — AWS DynamoDB через пакет
aws/aws-sdk-php. Ключи конфига:key,secret,region,table. - array — in-memory, только на время запроса. Применяется в тестах.
- null — отключает кэш полностью, всегда возвращает
null. Удобен при отладке.
Основные методы Cache-фасада
<?php
use Illuminate\Support\Facades\Cache;
// Положить значение на 60 секунд
Cache::put('user:42', $user, 60);
// Получить или выполнить замыкание и закешировать
$user = Cache::remember('user:42', 300, function () {
return User::find(42);
});
// Вечное хранение
Cache::forever('settings', $settings);
// Атомарный increment / decrement
Cache::increment('page_views');
Cache::decrement('stock:item:7', 5);
// Удалить ключ
Cache::forget('user:42');
// Проверить наличие
if (Cache::has('user:42')) {
// ...
}
// Теги (только для redis / memcached)
Cache::tags(['users', 'profiles'])->put('user:42', $user, 600);
Cache::tags(['users'])->flush(); // сброс всей группы
Переключение хранилища на лету
<?php
// Использовать конкретный store вне зависимости от CACHE_STORE
$value = Cache::store('redis')->get('key');
Cache::store('database')->put('key', 'value', 120);
Конфигурация Redis-драйвера
// config/cache.php
'stores' => [
'redis' => [
'driver' => 'redis',
'connection' => 'cache', // секция из config/database.php
'lock_connection' => 'default',
],
],
// config/database.php
'redis' => [
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
Атомарные блокировки
<?php
$lock = Cache::lock('process:invoice:42', 10);
try {
$lock->block(5); // ждать до 5 сек, затем LockTimeoutException
// защищённый блок
} finally {
$lock->release();
}
Подводные камни
- Теги недоступны для file и database драйверов — при переходе с array/redis на file в тестах тегированные операции бросают
BadMethodCallException. - Cache::remember не атомарен — при параллельных запросах несколько процессов могут одновременно пройти cache miss и перегрузить БД. Используйте
Cache::lock+rememberдля «dog-pile» защиты. - Сериализация объектов — Eloquent-модели сериализуются целиком вместе с relations; при изменении структуры модели старый кэш может вызвать ошибку десериализации.
- TTL = 0 в Laravel < 9 — в старых версиях
put('key', $val, 0)означало вечное хранение, в новых версиях — немедленное истечение. Используйтеforever()явно. - CACHE_PREFIX конфликты — несколько окружений на одном Redis без разных
CACHE_PREFIXперезаписывают ключи друг друга. - database драйвер и индекс — без индекса на колонке
expirationтаблицыcacheзапросphp artisan cache:prune-stale-tagsи автоочистка устаревших записей деградируют по скорости. - Redis cluster и хеш-теги — в Redis Cluster ключи с тегами должны находиться на одном шарде. Laravel использует хеш-теги
{tag}автоматически, но при ручных операциях сphpredisэто легко сломать.
Common mistakes
- Сводить caching к названию метода без lifecycle и failure path.
- Игнорировать модель runtime: Laravel 13 поверх PHP: request проходит через HTTP kernel, middleware, routing, controller/action и response pipeline.
- Не отделять validation, authorization, transaction boundary и business logic.
- Не обсуждать idempotency, retries, shutdown и observability.
What the interviewer is testing
- Объясняет caching через конкретную точку lifecycle в Laravel.
- Приводит корректный минимальный пример без вымышленных методов или callbacks.
- Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.
- Связывает решение с метриками, backpressure, retry policy и graceful shutdown.