Sobes.tech
Senior

10 applications gestionnaires récupèrent constamment des tâches de la base de données et les traitent. Comment éviter que deux instances de l'application prennent en charge la même tâche?

sobes.tech IA

Réponse de l'IA

Чтобы избежать ситуации, когда два приложения одновременно берут в работу одну и ту же задачу из базы данных, можно использовать следующие подходы:

  1. Блокировка на уровне базы данных (pessimistic locking)

    • Использовать транзакции с блокировкой строк (SELECT ... FOR UPDATE), чтобы при чтении задачи она блокировалась для других приложений.
  2. Оптимистичная блокировка

    • Добавить в таблицу поле версии или метку времени.
    • При попытке взять задачу в работу обновлять это поле с проверкой, что версия не изменилась.
    • Если обновление прошло успешно — задача взята, иначе — кто-то другой уже взял.
  3. Атомарное обновление статуса задачи

    • Выполнить запрос, который одновременно выбирает и помечает задачу как "в работе".
    • Например, UPDATE tasks SET status = 'processing' WHERE status = 'pending' LIMIT 1 RETURNING *.
    • Таким образом, только одно приложение получит задачу.
  4. Использование очередей сообщений

    • Вместо прямого опроса базы использовать очередь (RabbitMQ, Kafka, Redis Streams), где задачи распределяются между потребителями.
  5. Использование распределенных блокировок

    • Например, с помощью Redis (Redlock) или ZooKeeper для координации доступа к задачам.

Пример атомарного обновления в SQL:

UPDATE tasks
SET status = 'processing', worker_id = :workerId
WHERE id = (
  SELECT id FROM tasks WHERE status = 'pending' LIMIT 1
)
RETURNING *;

Это гарантирует, что одна задача будет взята только одним приложением.

Таким образом, ключ — обеспечить атомарность операции выбора и пометки задачи, чтобы избежать гонок между приложениями.