Реализация горизонтального кеширования в PHP с Redis Cluster

557cb36d260ec3fc321622f2ec889935.jpg

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

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

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

Установка Redis

Первый шаг — установка Redis на сервер. Если у вас собственный сервер, выполните следующие шаги:

  1. Подключитесь к вашему серверу через SSH:

    ssh [USERNAME]@[IP_ADDRESS]
  2. Обновите пакеты:

    sudo apt update && sudo apt upgrade
  3. Установите Redis:

    sudo apt install redis-server
  4. Запустите и включите Redis:

    sudo systemctl start redis
    sudo systemctl enable redis
  5. Проверьте статус Redis:

    sudo systemctl status redis

Теперь Redis установлен и готов к использованию.

Настройка конфигурации Redis Cluster

Чтобы создать кластер, нужно немного поработать с конфигурационными файлами, особенно с redis.conf.

  1. Откройте файл конфигурации:

    sudo nano /etc/redis/redis.conf
  2. Обратите внимание на следующие параметры безопасности. Важно отключить protected-mode для работы кластера, но имейте в виду, что это увеличивает риск доступа извне:

    protected-mode no
  3. Укажите IP-адреса для соединений:

    bind 127.0.0.1 [SERVER_IP_ADDRESS]
  4. Активируйте кластерный режим:

    cluster-enabled yes
    cluster-config-file nodes-6379.conf
    cluster-node-timeout 15000
  5. Включите appendonly для повышения надежности данных:

    appendonly yes
  6. После внесения изменений перезапустите Redis:

    sudo systemctl restart redis
  7. Не забудьте открыть необходимые порты:

    sudo ufw allow 6379
    sudo ufw allow 16379

Создание Redis Cluster

Теперь создадим кластер с помощью утилиты redis-cli.

Используйте следующую команду для создания кластера:

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 сообщит, что все 16384 слота распределены, что подтверждает успешное создание кластера.

Подключитесь к кластеру и проверьте его состояние:

redis-cli -c -p 7000

Теперь можно использовать команды, такие как SET и GET, чтобы взаимодействовать с вашим кластером.

Интеграция Redis Cluster с PHP

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

Пора подключить Redis к вашему PHP-приложению. PhpRedis — это расширение PHP, которое предоставляет низкоуровневый доступ к Redis и поддерживает все его функции, включая работу с кластерами.

  1. Установите PhpRedis с помощью PECL:

    pecl install redis
  2. Добавьте следующую строку в ваш php.ini:

    extension=redis.so
  3. Создайте соединение с кластером:

    $redisCluster = new RedisCluster('mycluster', ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7002']);

Теперь можно использовать команды Redis:

$redisCluster->set("my_key", "Hello, Redis!");
echo $redisCluster->get("my_key"); // Вывод: Hello, Redis!

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

try {
    $value = $redisCluster->get("unknown_key");
    echo $value ? $value : "Key does not exist!";
} catch (RedisException $e) {
    echo "Redis error: " . $e->getMessage();
}

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

Predis — это клиентская библиотека для Redis на PHP, которая не требует установки дополнительных расширений.

  1. Установите Predis:

    composer require predis/predis
  2. Создайте соединение:

    require 'vendor/autoload.php';
    
    $client = new Predis\Client([
        'cluster' => 'redis',
        'parameters' => [
            'host' => '127.0.0.1',
            'port' => 7000,
        ],
    ]);
  3. Работайте с данными:

    $client->set('test_key', 'Hello from Predis!');
    $value = $client->get('test_key');
    echo $value; // Вывод: Hello from Predis!

Основные команды и их применение

Работа с простыми ключами

sudo systemctl status redis

Работа с хэшами

$client->hset("user:1000", "name", "John Doe");
$client->hset("user:1000", "email", "john@example.com");

$user = $client->hgetall("user:1000");
print_r($user);

Работа со списками

$client->rpush("task_queue", "Task 1");
$client->rpush("task_queue", "Task 2");

$tasks = $client->lrange("task_queue", 0, -1);
print_r($tasks);

Настройка времени жизни ключей

$client->setex("temporary_key", 300, "This key expires in 5 minutes.");

Работа с командой MSET и MGET

$client->mset(["key1" => "value1", "key2" => "value2"]);
$values = $client->mget(["key1", "key2"]);
print_r($values);

Реализация горизонтального кеширования в PHP

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

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

function writeThrough($key, $value) {
    global $redis;
    $redis->set($key, $value);
    saveToDatabase($key, $value);
}

Write-Behind кеширование сначала записывает данные в кеш, а затем в БД, что улучшает время отклика:

function writeBehind($key, $value) {
    global $redis;
    $redis->set($key, $value);
    queueForDatabaseInsert($key, $value);
}

С TTL можно управлять памятью, автоматически удаляя ключи после истечения времени:

function cacheWithTTL($key, $value, $ttl) {
    global $redis;
    $redis->setex($key, $ttl, $value);
}

Пример использования кеширования для API-запросов

Настройте соединение с Redis:

require 'vendor/autoload.php';

$redis = new Predis\Client([
    'cluster' => 'redis',
    'parameters' => [
        'host' => '127.0.0.1',
        'port' => 7000,
    ],
]);

Создайте функцию для получения данных из кеша или базы:

function getCachedData($key) {
    global $redis;
    if ($redis->exists($key)) {
        return $redis->get($key);
    } else {
        $data = getDataFromDatabase($key);
        $redis->setex($key, 3600, $data); // Кешируем данные на 1 час
        return $data;
    }
}

function getDataFromDatabase($key) {
    $mysqli = new mysqli('localhost', 'user', 'password', 'database');
    $result = $mysqli->query("SELECT value FROM table WHERE key='$key'");
    return $result->fetch_assoc()['value'];
}

Пример использования функции

$key

 = "user:123";
$data = getCachedData($key);
echo "Данные: " . $data;

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

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

© Habrahabr.ru