Налаштування Redis Cluster для масштабування
Одиничний Redis обмежений RAM одного сервера та пропускною спроможністю одного CPU ядра (Redis однопоточний для операцій над даними). Redis Cluster вирішує обидві проблеми: дані шардуються по вузлах, кожен вузол відповідає за свій діапазон ключів. 6 вузлів (3 master + 3 replica) — мінімальна конфігурація кластера.
Як працює шардування
Redis Cluster ділить простір ключів на 16 384 хеш-слоти. Кожен master-вузол відповідає за діапазон слотів. При операції з ключем Redis обчислює CRC16(key) % 16384 та маршрутизує запит на потрібний вузол.
При додаванні нового вузла — слоти мігрують між вузлами без зупинки кластера. Клієнт отримує помилку MOVED при зверненню до слоту не на той вузол та автоматично переключається.
Встановлення 6-вузлового кластера
Конфігурація redis-cluster.conf для кожного вузла (змінюється тільки port):
port 7001
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
bind 0.0.0.0
requirepass ClusterPassword123
masterauth ClusterPassword123
# Репліцирование
replica-lazy-flush no
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
# Продуктивність
tcp-backlog 511
hz 10
aof-rewrite-incremental-fsync yes
Запуск 6 інстансів (порти 7001–7006):
for port in 7001 7002 7003 7004 7005 7006; do
mkdir -p /var/redis/$port
cp redis-cluster.conf /var/redis/$port/redis.conf
sed -i "s/port 7001/port $port/" /var/redis/$port/redis.conf
sed -i "s/nodes-7001/nodes-$port/" /var/redis/$port/redis.conf
redis-server /var/redis/$port/redis.conf --daemonize yes
done
Створення кластера:
redis-cli --cluster create \
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 127.0.0.1:7006 \
--cluster-replicas 1 \
-a ClusterPassword123
--cluster-replicas 1 — одна реплика на кожен master. Redis автоматично розподіляє: 3 master (7001, 7002, 7003) та 3 реплики (7004, 7005, 7006).
Docker Compose для розробки
version: '3'
services:
redis-cluster:
image: grokzen/redis-cluster:7.0.10
ports:
- "7001-7006:7001-7006"
environment:
IP: 127.0.0.1
INITIAL_PORT: 7001
MASTERS: 3
SLAVES_PER_MASTER: 1
MAX_MEMORY: 256mb
MAX_MEMORY_POLICY: allkeys-lru
Обмеження Cluster: хеш-теги
У кластері не можна виконувати multi-key команди (MGET, MSET, пайплайн), якщо ключи на різних слотах. Для групування ключів на одному слоті — хеш-теги: частина ключа в {} використовується для обчислення слоту.
# Ці ключі потрапляють на різні слоти — MGET не працює
MGET user:1:profile user:2:profile
# З хеш-тегом {user:1} — обидва на одному слоті
SET {user:1}:profile "..."
SET {user:1}:settings "..."
MGET {user:1}:profile {user:1}:settings # OK
У Laravel — налаштування хеш-тегів для трансакцій:
// Впевніться, що ключі з {user:1} сегментом потрапляють на один слот
Cache::tags(["user:{$userId}"])->put("profile", $data, 3600);
Cache::tags(["user:{$userId}"])->put("settings", $data, 3600);
Cache::tags(["user:{$userId}"])->flush();
Підключення клієнтів до кластера
PHP з phpredis:
$redis = new RedisCluster(null, [
'127.0.0.1:7001',
'127.0.0.1:7002',
'127.0.0.1:7003',
], 1.5, 1.5, true, 'ClusterPassword123');
// phpredis автоматично маршрутизує по слотам
$redis->set('key', 'value');
$redis->get('key');
Predis:
use Predis\Client;
$client = new Client(
[
'tcp://127.0.0.1:7001?password=ClusterPassword123',
'tcp://127.0.0.1:7002?password=ClusterPassword123',
'tcp://127.0.0.1:7003?password=ClusterPassword123',
],
['cluster' => 'redis']
);
Laravel config/database.php:
'redis' => [
'client' => 'phpredis',
'options' => [
'cluster' => 'redis',
'prefix' => '',
'parameters' => ['password' => env('REDIS_PASSWORD')],
],
'clusters' => [
'default' => [
['host' => '127.0.0.1', 'port' => 7001, 'password' => env('REDIS_PASSWORD')],
['host' => '127.0.0.1', 'port' => 7002, 'password' => env('REDIS_PASSWORD')],
['host' => '127.0.0.1', 'port' => 7003, 'password' => env('REDIS_PASSWORD')],
],
],
],
Управління кластером
# Статус кластера
redis-cli -c -p 7001 -a ClusterPassword123 cluster info
# Вузли та їх ролі
redis-cli -c -p 7001 -a ClusterPassword123 cluster nodes
# Перевірка розподілу слотів
redis-cli --cluster check 127.0.0.1:7001 -a ClusterPassword123
# Додавання нового master-вузла
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001 -a ClusterPassword123
# Перерозподіл слотів на новий вузол
redis-cli --cluster reshard 127.0.0.1:7001 -a ClusterPassword123
# Додавання реплики до нового вузла
redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 \
--cluster-slave --cluster-master-id <master-node-id> \
-a ClusterPassword123
Failover
При падінні master-вузла реплика автоматично підвищується до master (в течение cluster-node-timeout, за замовчуванням 5 секунд). Приложення отримує помилку CLUSTERDOWN в цей час — потрібно передбачити retry логіку.
// Retry при CLUSTERDOWN
$attempts = 0;
while ($attempts < 3) {
try {
$result = $redis->get($key);
break;
} catch (\RedisClusterException $e) {
if (++$attempts >= 3) throw $e;
usleep(500000); // 500ms
}
}
Мониторинг
# Метрики кожного вузла
for port in 7001 7002 7003 7004 7005 7006; do
echo "=== Node $port ==="
redis-cli -p $port -a ClusterPassword123 INFO replication | grep -E "role|master_host|connected_slaves"
done
Prometheus redis_exporter уміє збирати метрики кластера — вказувати тільки один з вузлів, він сам обійде решту через cluster nodes.
Строки виконання
Розгортання Redis Cluster з 6 вузлів з налаштуванням, тестуванням failover та мониторингом — 2–3 робочих дня. Адаптація існуючого додатку під cluster (хеш-теги, клієнтський кластер, обробка MOVED/ASK помилок) — 1–2 дня в залежності від складності використання Redis у коді.







