Кэширование в PHP: Redis, Memcached и встроенные решения: от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему кэширование — основа быстрого PHP-приложения

Каждый разработчик PHP рано или поздно сталкивается с проблемой производительности. Когда база данных начинает тормозить, а страницы грузятся по 3-5 секунд, первое, что приходит на ум — кэширование. Это не просто "сохранить данные куда-то", это целая философия оптимизации.

В этой статье мы разберём все популярные подходы к кэшированию в PHP: от простого файлового кэша до промышленных решений на Redis и Memcached. Вы узнаете, как выбрать правильный инструмент и избежать типичных ошибок. Поехали!

1. Встроенные механизмы кэширования в PHP

1.1. Кэширование опкода: OPcache

Прежде чем говорить о внешних хранилищах, стоит вспомнить, что PHP сам умеет кэшировать свой код. Механизм OPcache сохраняет скомпилированные скрипты в оперативной памяти, избавляя PHP от необходимости каждый раз парсить и компилировать файлы.

Включение OPcache в php.ini:

opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2

Это первая линия обороны. Без OPcache любое другое кэширование будет менее эффективно.

1.2. APCu — пользовательский кэш в памяти

APCu (Alternative PHP Cache) — это расширение для хранения произвольных данных в общей памяти процесса PHP. Идеально подходит для небольших проектов, где не требуется распределённое кэширование.

Пример работы с APCu:

<?php
// Сохраняем данные на 5 минут
apcu_store('my_key', ['data' => 'value'], 300);

// Читаем данные
$data = apcu_fetch('my_key');
if ($data === false) {
    echo "Кэш не найден, генерируем заново";
}

// Удаляем ключ
apcu_delete('my_key');
?>

Плюсы: молниеносная скорость, простота. Минусы: данные живут только в рамках одного сервера.

2. Memcached: простота и скорость

2.1. Что такое Memcached и зачем он нужен

Memcached — это распределённая система кэширования в оперативной памяти. Она была создана для ускорения динамических веб-приложений путём снижения нагрузки на базы данных. В отличие от APCu, Memcached работает как отдельный сервер, к которому можно подключаться с разных инстансов PHP.

2.2. Установка и подключение Memcached

Сначала установите сервер Memcached:

sudo apt install memcached
sudo systemctl start memcached

Затем установите PHP-расширение:

sudo pecl install memcached

Теперь можно работать с кэшем:

<?php
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);

// Сохраняем на 10 минут
$memcached->set('user_123', ['name' => 'Иван', 'email' => 'ivan@example.com'], 600);

// Читаем
$user = $memcached->get('user_123');
if ($user === false) {
    // Загружаем из БД
}
?>

2.3. Когда выбирать Memcached

  • Когда нужно простое key-value хранилище
  • Когда данные имеют короткий срок жизни (сессии, временные данные)
  • Когда не требуется персистентность (Memcached не сохраняет данные на диск)

3. Redis: мощный инструмент для сложных сценариев

3.1. Почему Redis лучше Memcached?

Redis — это не просто кэш, это полноценная in-memory база данных с поддержкой сложных структур данных: списки, множества, хэши, битовые карты. В отличие от Memcached, Redis поддерживает:

  • Персистентность — данные не пропадают при перезагрузке
  • Транзакции и Lua-скрипты
  • Pub/Sub для обмена сообщениями
  • Репликацию и кластеризацию

3.2. Примеры работы с Redis в PHP

Для работы с Redis используйте библиотеку predis/predis (composer) или расширение phpredis.

Установка через Composer:

composer require predis/predis

Базовый пример:

<?php
require 'vendor/autoload.php';

$client = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
]);

// Сохраняем данные с TTL 1 час
$client->setex('user:456', 3600, json_encode(['name' => 'Мария']));

// Читаем
$user = $client->get('user:456');
if ($user) {
    $user = json_decode($user, true);
}

// Инкремент счётчика (популярно для ограничения запросов)
$client->incr('page_views');
$client->expire('page_views', 86400); // сброс через сутки
?>

3.3. Кэширование сложных запросов с Redis

Реальный пример: кэширование результатов выборки из БД с автоматическим обновлением:

<?php
function getArticles($categoryId) {
    global $client, $pdo;
    
    $cacheKey = "articles:category:$categoryId";
    
    // Пытаемся достать из Redis
    $cached = $client->get($cacheKey);
    if ($cached) {
        return json_decode($cached, true);
    }
    
    // Если нет в кэше — идём в БД
    $stmt = $pdo->prepare("SELECT * FROM articles WHERE category_id = ?");
    $stmt->execute([$categoryId]);
    $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Сохраняем в кэш на 15 минут
    $client->setex($cacheKey, 900, json_encode($articles));
    
    return $articles;
}
?>

4. Сравнение и выбор стратегии кэширования

4.1. Сводная таблица

Блоги

Рекомендаций по книгам