Комментарии 6
Можно сервису, сохраняющему задачи на скачивание в базу, сразу публиковать их в кафку. Тогда воркеры сразу их будут разбирать по своим партициям, а крон оставить запасным вариантом.
Тоже об этом сразу подумалось. А если публиковать в rabbit, то и партиционированием не нужно будет управлять
Тут есть 2 проблемы:
рассинхронизирования баз данных (основная vs. kafka) если kafka лежит
медленные воркеры все также блокируют все очередь (или одну partition)
Подход с transactional sandbox или BD+CDC вполне стандартный подход в данном случае.
Альтернативой может быть какой-то pub/sub, но тут надо дробить входящие сообщения. Скорее всего несколько уровней очередей - первая принять большой документ, вторая раздробить его, и дальше уже workers которые будут скачивать изображения и обновлять базу. Да и это довольно рискованная смена архитектуры по сравнение с тем, что было до обновления.
Инкрементальное улучшение существующей архитектуры описанное в статье вполне логичное решение. Этот ход купил достаточно времени при малейших затратах, ну а дальше можно подумать о более радикальных изменениях
Что такое BD+CDC?
Опечатка: DB (Data Base) + CDC (Change data capture). Например Posgres + Debezium
При старте каждый воркер будет идти в базу и в рамках своего лимита получать список id свободных задач. После этого он будет пытаться назначить эти задачи на себя — по сути, просто делать update-запрос, пытаясь проставить им свой worker_id.
видно, что скорость падает из-за лишней нагрузкой на БД из-за повторения запросов.
А какая у вас БД?
В postgresql можно использовать блокировку на строки + обновление в одном запросе. Тогда не будет перезапросов.
UPDATE
task_table
SET
version = version + 1,
available_after = now() at time zone 'utc' + @lockInterval,
worker_id = @workerId
WHERE
id IN (
SELECT id
FROM task_table
WHERE
(available_after is null OR available_after < now() at time zone 'utc')
AND completed_at is null
ORDER BY id
LIMIT 1000
FOR UPDATE SKIP LOCKED
)
RETURNING *, now() at time zone 'utc' - created_at AS Lifetime
Подзапрос ищет первые 1000 не заблокированных строк, обновление берёт строки в обработку без гонок.
Как мы выдержали x20 рост нагрузки на сервис Авито Автозагрузка