Распределённые блокировки, лидерство, часы
↑ 8.3 Микросервисы и распределённые системы · ← Предыдущая · → Следующая
Зачем это на собесе
«Как выполнить задачу только в одном инстансе» — практический вопрос, за которым скрыты тонкости распределённых систем.
Объяснение
Распределённая блокировка — взаимное исключение между процессами на разных узлах.
| Способ | Особенности |
|---|---|
PostgreSQL advisory lock (pg_advisory_lock) | просто, если БД уже есть, освобождается при потере соединения |
Redis (SET key val NX PX 30000) | быстро; риски при отказе мастера; Redlock спорный |
| etcd / ZooKeeper / Consul | лидерство, сессии, строгая согласованность (консенсус Raft/Zab) |
| Kubernetes Lease | leader 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).
Практика
- Реализуйте advisory lock в PostgreSQL для периодической задачи.
- Опишите сценарий с паузой GC и решите fencing token.
- Замените блокировку на партиционирование сообщений по ключу.
Вопросы с ответами
Почему распределённые блокировки сложны?
Возможны сетевые задержки, паузы процессов и расхождения часов: владелец может считать, что блокировка у него, когда она уже истекла.
Что такое fencing token?
Растущий номер, выдаваемый с блокировкой; хранилище отвергает операции с устаревшим номером.