Распределённые блокировки, лидерство, часы

↑ 8.3 Микросервисы и распределённые системы · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

«Как выполнить задачу только в одном инстансе» — практический вопрос, за которым скрыты тонкости распределённых систем.

Объяснение

Распределённая блокировка — взаимное исключение между процессами на разных узлах.

СпособОсобенности
PostgreSQL advisory lock (pg_advisory_lock)просто, если БД уже есть, освобождается при потере соединения
Redis (SET key val NX PX 30000)быстро; риски при отказе мастера; Redlock спорный
etcd / ZooKeeper / Consulлидерство, сессии, строгая согласованность (консенсус Raft/Zab)
Kubernetes Leaseleader election для контроллеров
Строка в БД с SELECT ... FOR UPDATE SKIP LOCKEDочереди задач, «захват» работы
// Redis: захват с TTL и уникальным токеном
var token = Guid.NewGuid().ToString();
if (await db.StringSetAsync("lock:report", token, TimeSpan.FromSeconds(30), When.NotExists))
{
    try { await RunJobAsync(ct); }
    finally { await db.ScriptEvaluateAsync("if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end", [ "lock:report" ], [ token ]); }
}

Fencing token — монотонно растущий номер вместе с блокировкой; ресурс отклоняет запросы со старым токеном. Без него «зависший» процесс после истечения TTL может испортить данные.

Leader election — выбор одного лидера среди реплик (для фоновых задач, планировщика). Консенсус: Raft, Paxos.

Часы: физические часы расходятся (NTP, drift), скачут; на них нельзя строить порядок событий и истечение блокировок. Альтернативы: логические часы (Lamport), векторные часы, монотонные счётчики, TrueTime (Spanner).

Нюансы и подводные камни

  • Пауза процесса (GC, swap) дольше TTL блокировки: два «владельца» одновременно.
  • Блокировка не заменяет идемпотентность — делайте операции безопасными к повтору.
  • Избегайте блокировок: очередь с единственным потребителем на ключ, партиционирование по ключу (Kafka).
  • Redis-лок на одном узле теряется при перезапуске и failover.
  • Сложные лидерские схемы проще делегировать инфраструктуре (Kubernetes, planner).

Практика

  1. Реализуйте advisory lock в PostgreSQL для периодической задачи.
  2. Опишите сценарий с паузой GC и решите fencing token.
  3. Замените блокировку на партиционирование сообщений по ключу.

Вопросы с ответами

Связанные темы