@siarheipashkevich
developer

Как запретить одновременные (одинаковые) входящие запросы на стороне API?

Коллеги, всем привет.
Словил проблему при синхронизации данных между разными сайтами.

Есть сайт A с которого собираются данные о чеках и отправляются на сайт Б пачками по 1000шт последовательно. На сайте А сделали блокировку кнопки от повторного нажатия и т.д., но всё равно что-то случилось, что на сайт Б прилетели дубликаты запросов в одно и тоже время.

На сайте Б мы ждём входящих запросов с пачками чеков по 1000, проверяем каждый чек по отдельности, что он не существует в бд для сайта БД и после проверки сохрянем их в бд. И ждём следующую пачку чеков. Обработка одной пачки, занимает ~30 сек., всё работало год хорошо, но что-то случилось, что пришли одновременно запросы и данные задублировались, так как первый запрос не успел положить в бд данные и из-за этого второй запрос прошёл валидацию с дублирующей информацией.

Как можно решать такие проблемы на стороне API?
  • Вопрос задан
  • 169 просмотров
Пригласить эксперта
Ответы на вопрос 2
@Quadrollionaire
Не думаю что это лучшее решение, но как вариант.
1) Вычисляете хэш (либо идентификаторов чеков, либо еще чего нить, но главное чтоб запрос можно было уникализировать)
2) Добавляете это все в редис, rabbit, kafka (лучше кафка если нужна какая-никакая, гарантия, хотя с тем же редисом ее тоже можно достигнуть за счет правильного конфига)
3) Создаете обработчики которые читают очередь и выполняют всю работу

P.S.) Можете обойтись и без хэша просто записывая в редис обработанные чеки за последние пол дня к примеру и когда прилетает запрос, смотрите какие уже обработаны, их не добавляете в очередь, а те что новые - пускаете в дальнейший путь. В таком случае и уникализировать ничего не надо (гемора меньше)
Ответ написан
Laravel прекрасен и продуман ) В нём есть и заготовка для организации Очереди задач.

В общем ваша задача выглядит как преобразование из возможно параллельных запросов в последовательные.
Очередь задач с единственным рабочим для этого вполне подходит.

Через artisan создайте новый Job и перенесите в него логику обработки запроса. При поступлении api запроса просто создавайте новую задачу и возвращайте мгновенно ответ "Ок, принято".

Рабочий будет постоянно работать: обрабатывать долгоиграющую пачку или ожидать поступления новой задачи. Точно не возьмётся за 2 параллельно.

p.s. почему так долго обрабатываются 1000 чеков? База тормозит при вставке? Индексы не те?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы