Redis Cluster, Sentinel, replication, production checklist
Для масштабирования beyond single node Redis предлагает репликацию, Sentinel для отказоустойчивости, и Redis Cluster для шардирования. Production развёртывание требует понимания этих механизмов и следования best practices.
Репликация — копирование данных с master на replica (slave). Реплики только для чтения, данные асинхронно копируются с мастера.
# redis.conf для replica
# Указать master
replicaof <master-ip> <master-port>
# Например:
replicaof 192.168.1.100 6379
# Мастер пароль (если требуется)
masterauth <master-password>
# Реплика только для чтения (по умолчанию yes)
replica-read-only yes
# Приоритет для Sentinel (меньше = выше приоритет)
replica-priority 100# На мастере
INFO replication
# Вывод:
# role:master
# connected_slaves:2
# slave0:ip=192.168.1.101,port=6379,state=online,offset=123456
# slave1:ip=192.168.1.102,port=6379,state=online,offset=123456
# На реплике
INFO replication
# Вывод:
# role:slave
# master_host:192.168.1.100
# master_port:6379
# master_link_status:up
# slave_repl_offset:123456Репликация асинхронна: мастер не ждёт подтверждения от реплик. Это означает возможную потерю данных при сбое мастера до репликации.
# Минимальное количество реплик для записи
CONFIG SET min-replicas-to-write 1
CONFIG SET min-replicas-max-lag 10 # Максимальная задержка в секундахЕсли меньше min-replicas-to-write реплик доступны или задержка больше min-replicas-max-lag, мастер возвращает ошибку.
Sentinel — система мониторинга и автоматического failover. Не обеспечивает шардирование, только отказоустойчивость.
┌─────────────┐ ┌─────────────┐
│ Sentinel 1 │ │ Sentinel 2 │
└──────┬──────┘ └──────┬──────┘
│ │
└────────┬──────────┘
│
┌────────▼────────┐
│ Master │
│ 192.168.1.100 │
└────────┬────────┘
│
┌────────┴────────┐
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ Replica 1 │ │ Replica 2 │
└─────────────┘ └─────────────┘
# sentinel.conf
# Порт Sentinel
port 26379
# Мониторинг master
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.1.100 6379 2
# Пароль master
sentinel auth-pass mymaster SuperSecretPassword
# Время для обнаружения master down (мс)
sentinel down-after-milliseconds mymaster 5000
# Параллельная синхронизация реплик при failover
sentinel parallel-syncs mymaster 1
# Таймаут failover (мс)
sentinel failover-timeout mymaster 60000
# Уведомления (скрипт)
sentinel notification-script mymaster /var/redis/notify.sh
# Перезапуск после failover
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh# Запуск Sentinel
redis-sentinel /path/to/sentinel.conf
# Или
redis-server /path/to/sentinel.conf --sentinelfrom redis import Redis
from redis.sentinel import Sentinel
# Синхронный клиент
sentinel = Sentinel(
[('sentinel1', 26379), ('sentinel2', 26379), ('sentinel3', 26379)],
socket_timeout=0.1,
)
# Получение master
master = sentinel.master_for(
'mymaster',
socket_timeout=0.1,
password='redis-password',
)
# Получение replica (для чтения)
slave = sentinel.slave_for(
'mymaster',
socket_timeout=0.1,
password='redis-password',
)
# Использование
master.set('key', 'value')
value = slave.get('key')# Async клиент
import redis.asyncio.sentinel as sentinel
async_sentinel = sentinel.Sentinel(
[('sentinel1', 26379), ('sentinel2', 26379)],
)
master = async_sentinel.master_for('mymaster')
slave = async_sentinel.slave_for('mymaster')Redis Cluster — встроенное решение для горизонтального шардирования данных.
┌─────────────────────────────────────────────────────────┐
│ Redis Cluster │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Master 1 │ │ Master 2 │ │ Master 3 │ │
│ │ Slots 0-5460│ │Slots 5461- │ │Slots 10923- │ │
│ │ │ │ 10922 │ │ 16383 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Replica 1 │ │ Replica 2 │ │ Replica 3 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
# Запуск 6 узлов (3 master + 3 replica)
redis-server --port 7000 --cluster-enabled yes --cluster-config-file nodes-7000.conf
redis-server --port 7001 --cluster-enabled yes --cluster-config-file nodes-7001.conf
redis-server --port 7002 --cluster-enabled yes --cluster-config-file nodes-7002.conf
redis-server --port 7003 --cluster-enabled yes --cluster-config-file nodes-7003.conf
redis-server --port 7004 --cluster-enabled yes --cluster-config-file nodes-7004.conf
redis-server --port 7005 --cluster-enabled yes --cluster-config-file nodes-7005.conf
# Создание кластера
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 1from redis.cluster import RedisCluster
# Синхронный клиент
rc = RedisCluster(
host='192.168.1.100',
port=7000,
password='redis-password',
decode_responses=True,
socket_timeout=5,
socket_connect_timeout=5,
)
# Использование
rc.set('key', 'value')
value = rc.get('key')# Async клиент
import redis.asyncio.cluster as redis_cluster
async with redis_cluster.RedisCluster(
host='localhost',
port=7000,
password='redis-password',
decode_responses=True,
) as rc:
await rc.set('key', 'value')
value = await rc.get('key')Для группировки связанных ключей на одном узле используйте hash tags:
# Эти ключи будут на одном узле (хэш от "user1001")
rc.set('user:1001:{profile}', {...})
rc.set('user:1001:{settings}', {...})
rc.set('user:1001:{posts}', {...})
# Без hash tags ключи могут быть на разных узлах
rc.set('user:1001:profile', {...})
rc.set('user:1001:settings', {...})# Информация о кластере
redis-cli -p 7000 CLUSTER INFO
# Слоты кластера
redis-cli -p 7000 CLUSTER SLOTS
# Узлы кластера
redis-cli -p 7000 CLUSTER NODES
# Проверка кластера
redis-cli --cluster check 127.0.0.1:7000
# Исправление проблем
redis-cli --cluster fix 127.0.0.1:7000
# Ребалансировка
redis-cli --cluster rebalance 127.0.0.1:7000# redis.conf
# Пароль
requirepass SuperSecretPassword123!
# Переименование опасных команд
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG ""
rename-command DEBUG ""
rename-command KEYS ""
rename-command SHUTDOWN ""
# Bind только на internal IP
bind 127.0.0.1 192.168.1.100
# Protected mode
protected-mode yes
# TLS для production
tls-port 6379
port 0 # Отключить non-TLS
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt# Основные метрики
INFO server
INFO memory
INFO persistence
INFO stats
INFO replication
INFO cluster
# Ключевые метрики для мониторинга:
# - used_memory / maxmemory
# - mem_fragmentation_ratio
# - connected_clients
# - rejected_connections
# - evicted_keys
# - expired_keys
# - keyspace_hits / keyspace_misses (hit rate)
# - instantaneous_ops_per_sec
# - rdb_last_bgsave_status
# - aof_last_bgrewrite_status# redis.conf
loglevel notice
logfile /var/log/redis/redis-server.log
# Для отладки (не в production!)
# loglevel debug# Максимум клиентов
maxclients 10000
# Max memory
maxmemory 4gb
maxmemory-policy allkeys-lru
# Timeout бездействия
timeout 300
# TCP keepalive
tcp-keepalive 300#!/bin/bash
# backup-cluster.sh
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d)
# Бэкап каждого узла
for port in 7000 7001 7002 7003 7004 7005; do
redis-cli -p $port -a $PASSWORD BGSAVE
sleep 2
cp /var/lib/redis/$port/dump.rdb $BACKUP_DIR/dump-$port-$DATE.rdb
done
# Сжатие
tar -czf $BACKUP_DIR/cluster-$DATE.tar.gz $BACKUP_DIR/dump-*-$DATE.rdb
# Удаление старых бэкапов
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -deleteversion: '3.8'
services:
redis-node-0:
image: redis:7-alpine
command: redis-server --port 7000 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7000:7000"
volumes:
- redis-node-0:/data
redis-node-1:
image: redis:7-alpine
command: redis-server --port 7001 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7001:7001"
volumes:
- redis-node-1:/data
redis-node-2:
image: redis:7-alpine
command: redis-server --port 7002 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7002:7002"
volumes:
- redis-node-2:/data
redis-cluster-creator:
image: redis:7-alpine
depends_on:
- redis-node-0
- redis-node-1
- redis-node-2
command: >
redis-cli --cluster create
redis-node-0:7000 redis-node-1:7001 redis-node-2:7002
--cluster-replicas 0 --cluster-yes
volumes:
redis-node-0:
redis-node-1:
redis-node-2:| Аспект | Проверка |
|---|---|
| Пароль | requirepass установлен, сложный пароль |
| TLS | Включён для внешних подключений |
| Rename commands | FLUSHALL, CONFIG, DEBUG переименованы |
| Bind | Только internal IP, не 0.0.0.0 |
| Maxmemory | Установлен лимит 70-80% RAM |
| Eviction policy | allkeys-lru или volatile-lru |
| Perсистентность | RDB + AOF включены |
| Replication | Минимум 1 реплика на мастер |
| Sentinel/Cluster | Настроено для HA |
| Monitoring | Настроен сбор метрик и алерты |
| Backups | Автоматические бэкапы с проверкой |
| Slow log | Включён для анализа |
| Limits | maxclients, timeout установлены |
Проверьте понимание → ответьте на вопросы в cluster_prod.json
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.