Привет, Хабр!

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

Настройка Redis Cluster для горизонтального кеширования

Установка и базовая настройка Redis

Первым шагом будет установка Redis на сервер. Подключитесь к серверу через SSH и выполните следующие команды:

# Обновите пакеты
sudo apt update && sudo apt upgrade

# Установите Redis
sudo apt install redis-server

# Запустите и включите Redis
sudo systemctl start redis
sudo systemctl enable redis

Конфигурация Redis Cluster

  1. Включите кластерный режим и настройте надёжность данных. Откройте конфигурационный файл:

    sudo nano /etc/redis/redis.conf
  2. Установите следующие параметры:

    cluster-enabled yes
    cluster-config-file nodes-6379.conf
    cluster-node-timeout 15000
    appendonly yes
  3. Чтобы Redis работал безопасно, активируйте аутентификацию:

    requirepass your_secure_password
  4. Ограничиваем доступ к Redis с определённых IP-адресов, используя firewall:

    sudo ufw allow from  to any port 6379
    sudo ufw allow from  to any port 16379
  5. Перезапускаем Redis, чтобы применить изменения:

    sudo systemctl restart redis

Теперь создадим кластер из нескольких инстансов Redis, чтобы распределить нагрузку и обеспечить отказоустойчивость.

redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

Интеграция Redis Cluster с PHP для кеширования

Теперь подключим кластер к PHP, чтобы реализовать горизонтальное кеширование.

Установка и настройка PhpRedis

Для работы с Redis в PHP установите расширение PhpRedis:

pecl install redis

Добавляем расширение в файл php.ini:

extension=redis.so

Подключение к Redis Cluster

Создаем соединение с кластером в коде PHP. Включаем обработку ошибок для логирования и безопасности.

$redisCluster = new RedisCluster(null, ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7002'], 1.5, 1.5, true, 'your_secure_password');

Примеры горизонтального кеширования

Write-Through кеширование

В Write-Through кешировании данные записываются как в Redis, так и в основную БД, что позволяет обеспечить некую консистентность данных между ними.

function writeThroughCache($redisCluster, $key, $value) {
    global $database;
    $redisCluster->set($key, $value);
    saveToDatabase($database, $key, $value); // Обновление данных в базе
}

В этом примере сохраняем данные и в кеш, и в базу данных, чтобы избежать разночтений. Однако Write-Through увеличивает время отклика из-за доп. операции записи.

Write-Behind кеширование

В Write-Behind кешировании сначала записываются данные в Redis, а затем асинхронно синхронизируются с базой данных, что может уменьшить задержку.

function writeBehindCache($redisCluster, $key, $value) {
    global $database;
    $redisCluster->set($key, $value);
    queueForDatabaseInsert($database, $key, $value); // Асинхронная очередь для базы
}

С помощью Write-Behind стратегия кеширование становится быстрее, но в случае сбоя некоторые данные могут не попасть в базу.

Использование TTL для управления памятью

Чтобы автоматически удалять временные данные и оптимизировать использование памяти, задайте время жизни для ключей.

function cacheWithTTL($redisCluster, $key, $value, $ttl = 3600) {
    $redisCluster->setex($key, $ttl, $value); // Устанавливаем TTL 1 час
}

Пример кеширования API-ответов с Redis

Для демонстрации используем Redis Cluster для кеширования ответов от API.

function getCachedApiResponse($redisCluster, $key, $ttl = 3600) {
    // Проверяем наличие данных в кеше
    if ($redisCluster->exists($key)) {
        return $redisCluster->get($key);
    } else {
        // Запрос данных из API или базы данных
        $data = getApiResponse($key);
        
        // Сохраняем данные в кеш на 1 час
        $redisCluster->setex($key, $ttl, $data);
        return $data;
    }
}

Безопасная обработка ошибок

Для надёжности и безопасности логируйте ошибки Redis, а пользователю показывайте общее сообщение. Это помогает скрыть внутренние ошибки от внешних пользователей.

try {
    $data = getCachedApiResponse($redisCluster, "api:response:key");
    echo "Ответ: " . $data;
} catch (RedisException $e) {
    error_log("Redis error: " . $e->getMessage()); // Запись ошибки в журнал
    echo "Ошибка соединения. Пожалуйста, попробуйте позже.";
}

Заключение

Горизонтальное кеширование с использованием Redis Cluster позволяет эффективно распределить нагрузку и повысить отказоустойчивость системы. Реализация Write-Through и Write-Behind стратегий помогает адаптироваться под разные требования к кешу и обновлению данных.

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


Ну вот и всё — настроили кластер, подключили его к PHP, разобрались с кешированием — что ещё нужно для счастья? Главное, не забудьте про безопасность, а то Redis — товарищ отзывчивый, но доверчивый.

Больше практических кейсов эксперты OTUS рассматривают в рамках курсов, с полным списком которых можно ознакомиться в каталоге. Также напоминаю о том, что в календаре мероприятий вы можете записаться на любой интересующий вас вебинар.

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


  1. init0
    07.11.2024 03:45

    bind 127.0.0.1 [SERVER_IP_ADDRESS]

    sudo ufw allow 6379

    sudo ufw allow 16379

    И теперь нашим кластером может пользоваться кто угодно


  1. FanatPHP
    07.11.2024 03:45

    Важно обрабатывать возможные исключения:

    echo "Redis error: " . $e->getMessage();

    Прекрасная "обработка". Top notch. Пользователю сайта, конечно же, очень интересно наблюдать выскакивающие из ниоткуда сообщения об ошибках Редис, а программа, не получив нужные данные, спокойно продолжает работать с ними дальше. При этом исключения Predis внезапно обрабатывать уже не надо.

    Данные в БД почему-то хранятся в формате ключей Redis.

    SQL инъекция на этом фоне уже особо не удивляет. ChatGPT вообще не парится, а "писателю" обзоров тем более до лампочки.

    badcasedaily1 и "эксперты otus" в своём репертуаре. Стыд глаза не выест, а ссылочка на инфоцыганские "курсы" и копеечка за статью получены, можно двигаться дальше и писать обзор про что-нибудь ещё.


  1. grinsv
    07.11.2024 03:45

    В начале статьи надо бы добавить дисклеймер, что все описанное ниже справедливо для определенной конфигурации на сервере. Операционная система, к примеру, там явно должна быть debian-подобная.