Привет, Хабр!
В условиях высокой нагрузки стандартные подходы к кешированию не всегда справляются с запросами. В таких случаях на помощь приходит горизонтальное кеширование с 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
-
Включите кластерный режим и настройте надёжность данных. Откройте конфигурационный файл:
sudo nano /etc/redis/redis.conf
-
Установите следующие параметры:
cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 15000 appendonly yes
-
Чтобы Redis работал безопасно, активируйте аутентификацию:
requirepass your_secure_password
-
Ограничиваем доступ к Redis с определённых IP-адресов, используя firewall:
sudo ufw allow from to any port 6379 sudo ufw allow from to any port 16379
-
Перезапускаем 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)
FanatPHP
07.11.2024 03:45Важно обрабатывать возможные исключения:
echo "Redis error: " . $e->getMessage();
Прекрасная "обработка". Top notch. Пользователю сайта, конечно же, очень интересно наблюдать выскакивающие из ниоткуда сообщения об ошибках Редис, а программа, не получив нужные данные, спокойно продолжает работать с ними дальше. При этом исключения Predis внезапно обрабатывать уже не надо.
Данные в БД почему-то хранятся в формате ключей Redis.
SQL инъекция на этом фоне уже особо не удивляет. ChatGPT вообще не парится, а "писателю" обзоров тем более до лампочки.
badcasedaily1 и "эксперты otus" в своём репертуаре. Стыд глаза не выест, а ссылочка на инфоцыганские "курсы" и копеечка за статью получены, можно двигаться дальше и писать обзор про что-нибудь ещё.
grinsv
07.11.2024 03:45В начале статьи надо бы добавить дисклеймер, что все описанное ниже справедливо для определенной конфигурации на сервере. Операционная система, к примеру, там явно должна быть debian-подобная.
init0
И теперь нашим кластером может пользоваться кто угодно