Kubernetes resource limits: правильно выставляем requests и limits для подов
Redis из коробки — single-threaded процесс без встроенной отказоустойчивости. Если мастер упал, клиенты получают ошибки до ручного переключения. Sentinel и Cluster решают эту проблему, но по-разному: Sentinel обеспечивает автоматический failover для одного мастера, Cluster — шардирование данных с встроенной репликацией. Разберёмся, когда какой подход выбрать.
Sentinel: автоматический failover и кворум
Redis Sentinel — отдельный процесс, который мониторит master-replica топологию и выполняет автоматическое переключение при падении мастера. Минимум 3 Sentinel-инстанса для кворума:
# sentinel.conf
sentinel monitor mymaster 10.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1
Как работает failover:
- Sentinel пингует мастер каждую секунду. Если нет ответа
down-after-milliseconds— помечает как SDOWN (subjective down) - Когда кворум (2 из 3) Sentinel согласны — статус ODOWN (objective down)
- Один Sentinel выбирается лидером и промоутит реплику в мастер
- Остальные реплики переключаются на нового мастера
- Клиенты получают уведомление через Pub/Sub канал
+switch-master
Sentinel не шардирует данные. Все данные на одном мастере, реплики — для чтения и failover.
Cluster: шардирование по hash slots
Redis Cluster делит keyspace на 16384 hash slots. Каждый мастер-нод владеет частью слотов. Ключ попадает в слот по формуле CRC16(key) % 16384:
# Создать кластер из 6 нод (3 master + 3 replica)
redis-cli --cluster create \
10.0.0.1:6379 10.0.0.2:6379 10.0.0.3:6379 \
10.0.0.4:6379 10.0.0.5:6379 10.0.0.6:6379 \
--cluster-replicas 1
# Проверить распределение слотов
redis-cli --cluster check 10.0.0.1:6379
# Resharding: перенести слоты между нодами
redis-cli --cluster reshard 10.0.0.1:6379
Каждый мастер в кластере имеет свои реплики. При падении мастера его реплика автоматически промоутится — без внешнего Sentinel.
Сравнение: когда Sentinel, когда Cluster
+---------------------+------------------+--------------------+
| Критерий | Sentinel | Cluster |
+---------------------+------------------+--------------------+
| Шардирование | нет | 16384 hash slots |
| Макс. данных | RAM одной ноды | сумма всех нод |
| Failover | внешний процесс | встроенный |
| Multi-key операции | без ограничений | только в одном slot|
| Сложность | низкая | средняя |
| Минимум нод | 3 sentinel + 2 | 6 (3m + 3r) |
| Горизонт. масштаб. | только чтение | чтение + запись |
+---------------------+------------------+--------------------+
Sentinel хватает когда: данные помещаются в RAM одной ноды (до 64-128 GB), нужен простой failover, используются multi-key операции (MGET, транзакции, Lua-скрипты с несколькими ключами).
Cluster нужен когда: данные не помещаются на одну ноду, нужно горизонтальное масштабирование записи, готовы к ограничениям multi-key.
Клиентская сторона: подключение к Sentinel и Cluster
// ioredis: подключение через Sentinel
import Redis from 'ioredis';
const redis = new Redis({
sentinels: [
{ host: '10.0.0.10', port: 26379 },
{ host: '10.0.0.11', port: 26379 },
{ host: '10.0.0.12', port: 26379 }
],
name: 'mymaster', // имя из sentinel monitor
sentinelPassword: 'sentinel-pass',
password: 'redis-pass'
});
// ioredis: подключение к Cluster
const cluster = new Redis.Cluster([
{ host: '10.0.0.1', port: 6379 },
{ host: '10.0.0.2', port: 6379 },
{ host: '10.0.0.3', port: 6379 }
], {
redisOptions: { password: 'redis-pass' },
scaleReads: 'slave' // чтение с реплик
});
Клиент для Cluster должен обрабатывать MOVED и ASK redirects — ioredis делает это автоматически.
Подводные камни
- Split-brain в Sentinel — при сетевом разделении старый мастер продолжает принимать записи. После восстановления эти данные теряются. Защита:
min-replicas-to-write 1— мастер отказывает в записи без подтверждённых реплик - MOVED/ASK в Cluster — если клиент не поддерживает redirects, получите ошибки. Используйте cluster-aware клиенты
- Multi-key ограничения —
MGET key1 key2работает только если оба ключа в одном слоте. Решение: hash tags —{user:1}:nameи{user:1}:emailпопадут в один слот - Resharding под нагрузкой — перенос слотов создаёт нагрузку. Делайте в off-peak, контролируйте через
--cluster-pipeline
Практика: docker-compose для локальной разработки
Sentinel-стек (1 master + 2 replica + 3 sentinel):
services:
redis-master:
image: redis:7-alpine
command: redis-server --requirepass mypass
ports: ["6379:6379"]
redis-replica-1:
image: redis:7-alpine
command: redis-server --replicaof redis-master 6379 --masterauth mypass --requirepass mypass
depends_on: [redis-master]
redis-replica-2:
image: redis:7-alpine
command: redis-server --replicaof redis-master 6379 --masterauth mypass --requirepass mypass
depends_on: [redis-master]
sentinel-1:
image: redis:7-alpine
command: redis-sentinel /etc/sentinel.conf
volumes: ["./sentinel.conf:/etc/sentinel.conf"]
depends_on: [redis-master, redis-replica-1, redis-replica-2]
Для Cluster в Docker нужен --cluster-announce-ip на каждой ноде, иначе клиенты получат внутренние IP контейнеров и не смогут подключиться.
Начните с Sentinel — он проще в эксплуатации и покрывает 90% случаев. Переходите на Cluster только когда данные реально не помещаются на одну ноду или нужна горизонтальная запись.