Распределенная блокировка может остаться после падения процесса, потери сети или ошибки между захватом lock и секцией finally.
Простое удаление ключа опасно: к этому моменту TTL мог истечь, а блокировку уже получил другой процесс. Освобождать ее можно только с проверкой владельца.
Отличите зависший lock от долгой операции
Сначала нужен точный timeline захвата, продления, истечения и выполнения защищенной работы.
- Задача бесконечно сообщает, что ресурс занят.
- После перезапуска сервиса обработка не возобновляется.
- Два процесса выполняют одну операцию после истечения короткого TTL.
- Один worker удаляет lock, уже принадлежащий другому worker.
Почему возникает проблема
Lock ломается, когда срок аренды и реальное время работы не согласованы или нет уникального владельца.
- Блокировка создана без TTL либо TTL не устанавливается атомарно.
- Операция длится дольше lease, а продление не работает.
- Пауза процесса или сети мешает вовремя продлить lock.
- Освобождение выполняется обычным DEL без сравнения owner token.
- Критическая операция не защищена от устаревшего владельца после истечения lease.
Пошаговая диагностика
Логируйте идентификатор lock, безопасный owner ID, TTL и этап операции, но не чувствительные данные ресурса.
- Проверьте, создается ли lock атомарно с уникальным token и TTL.
- Сравните максимальную длительность операции с lease и интервалом продления.
- Найдите паузы GC, рестарты и сетевые таймауты рядом с инцидентом.
- Проверьте условие освобождения: удаляет ли lock только его владелец.
- Установите, может ли старый worker продолжить запись после потери аренды.
Lease не заменяет защиту ресурса
Даже корректный TTL не останавливает процесс, который не заметил потерю lock.
- Каждый захват получает уникальный owner token.
- Освобождение выполняется атомарным compare-and-delete.
- Продление допускается только текущему владельцу.
- Fencing token не позволяет устаревшему владельцу изменить ресурс.
Как исправить проблему
Исправьте протокол блокировки и сделайте защищенную операцию идемпотентной.
- Создавайте lock атомарно с TTL и случайным owner token.
- Продлевайте lease с запасом и прекращайте работу при потере владения.
- Освобождайте lock скриптом сравнения token и удаления.
- Передавайте монотонный fencing token в хранилище защищаемого ресурса.
- Добавьте идемпотентный ключ операции и уникальные ограничения данных.
Как проверить результат
- Падение worker освобождает ресурс после ограниченного TTL.
- Старый worker не удаляет и не продлевает чужой lock.
- Потерявший lease процесс не может записать устаревший результат.
- Повтор задачи не создает дубли бизнес-операции.
Типичные ошибки
- Удалять lock вручную без проверки владельца.
- Ставить TTL меньше обычной длительности операции.
- Считать try/finally достаточным при аварийном завершении процесса.
- Использовать lock как единственную защиту от дублей.
Как предотвратить повторение
- Мониторьте возраст lock, число продлений и потери lease.
- Тестируйте kill процесса и сетевые паузы в критической секции.
- Ограничивайте область и время удержания блокировки.
- Проектируйте бизнес-операции идемпотентными независимо от lock.
Когда нужна помощь
Если распределенная блокировка зависает или пропускает параллельные операции, я разберу timeline, TTL и код владельца, исправлю протокол освобождения и добавлю защиту от устаревших и повторных записей.