lenec ru

← все посты

Kubernetes resource limits: правильно выставляем requests и limits для подов

10K

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 только когда данные реально не помещаются на одну ноду или нужна горизонтальная запись.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.