Распределенная блокировка может остаться после падения процесса, потери сети или ошибки между захватом lock и секцией finally.

Простое удаление ключа опасно: к этому моменту TTL мог истечь, а блокировку уже получил другой процесс. Освобождать ее можно только с проверкой владельца.

Отличите зависший lock от долгой операции

Сначала нужен точный timeline захвата, продления, истечения и выполнения защищенной работы.

  • Задача бесконечно сообщает, что ресурс занят.
  • После перезапуска сервиса обработка не возобновляется.
  • Два процесса выполняют одну операцию после истечения короткого TTL.
  • Один worker удаляет lock, уже принадлежащий другому worker.

Почему возникает проблема

Lock ломается, когда срок аренды и реальное время работы не согласованы или нет уникального владельца.

  • Блокировка создана без TTL либо TTL не устанавливается атомарно.
  • Операция длится дольше lease, а продление не работает.
  • Пауза процесса или сети мешает вовремя продлить lock.
  • Освобождение выполняется обычным DEL без сравнения owner token.
  • Критическая операция не защищена от устаревшего владельца после истечения lease.

Пошаговая диагностика

Логируйте идентификатор lock, безопасный owner ID, TTL и этап операции, но не чувствительные данные ресурса.

  1. Проверьте, создается ли lock атомарно с уникальным token и TTL.
  2. Сравните максимальную длительность операции с lease и интервалом продления.
  3. Найдите паузы GC, рестарты и сетевые таймауты рядом с инцидентом.
  4. Проверьте условие освобождения: удаляет ли lock только его владелец.
  5. Установите, может ли старый worker продолжить запись после потери аренды.

Lease не заменяет защиту ресурса

Даже корректный TTL не останавливает процесс, который не заметил потерю lock.

  • Каждый захват получает уникальный owner token.
  • Освобождение выполняется атомарным compare-and-delete.
  • Продление допускается только текущему владельцу.
  • Fencing token не позволяет устаревшему владельцу изменить ресурс.

Как исправить проблему

Исправьте протокол блокировки и сделайте защищенную операцию идемпотентной.

  1. Создавайте lock атомарно с TTL и случайным owner token.
  2. Продлевайте lease с запасом и прекращайте работу при потере владения.
  3. Освобождайте lock скриптом сравнения token и удаления.
  4. Передавайте монотонный fencing token в хранилище защищаемого ресурса.
  5. Добавьте идемпотентный ключ операции и уникальные ограничения данных.

Как проверить результат

  • Падение worker освобождает ресурс после ограниченного TTL.
  • Старый worker не удаляет и не продлевает чужой lock.
  • Потерявший lease процесс не может записать устаревший результат.
  • Повтор задачи не создает дубли бизнес-операции.

Типичные ошибки

  • Удалять lock вручную без проверки владельца.
  • Ставить TTL меньше обычной длительности операции.
  • Считать try/finally достаточным при аварийном завершении процесса.
  • Использовать lock как единственную защиту от дублей.

Как предотвратить повторение

  • Мониторьте возраст lock, число продлений и потери lease.
  • Тестируйте kill процесса и сетевые паузы в критической секции.
  • Ограничивайте область и время удержания блокировки.
  • Проектируйте бизнес-операции идемпотентными независимо от lock.

Когда нужна помощь

Если распределенная блокировка зависает или пропускает параллельные операции, я разберу timeline, TTL и код владельца, исправлю протокол освобождения и добавлю защиту от устаревших и повторных записей.