Как справиться с дублирующейся строкой в BDD с помощью Symfony 5 и многопоточности?

#symfony #doctrine

#симфония #доктрина

Вопрос:

Мы создали приложение с Symfony 5, которое исследует веб-сайт и ссылки. Каждый процесс обнаружит все входящие ссылки a href и добавит их в базу данных URL. Для повышения производительности мы используем несколько процессов.

Проблема в том, что мы вставляем в базу данных один и тот же URL-адрес несколько раз, несмотря на проверку, если URL-адрес уже существует; потому что иногда 2 или более процесса вставляют один и тот же URL-адрес после того, как все они проверяют и ничего не возвращают.

Нам не удалось реализовать в doctrine эквивалент SQL INSERT при обновлении дубликата ключа. Можете ли вы просветить нас, какой процесс является правильным для решения такого рода проблем?

Мы собираемся добавлять повторяющуюся проверку при каждом запуске нового процесса, но мы хотели бы знать, является ли это лучшей практикой, если мы что-то упускаем.

Ответ №1:

какую «базу данных» вы используете? Если это СУБД, такая как MySQL, она не подходит для такого рода работы.

Я рекомендую переключиться на хранилище ключ-значение, что-то вроде Redis, это более эффективно для такого рода работы. Почему? Потому что redis является однопоточным, и каждая операция является атомарной. Это означает, что пока выполняется одна команда, никакая другая команда не будет выполняться. Таким образом, вы будете уверены, что если URL-адрес страницы (ключ) не существует, ваше приложение никогда не видело его раньше.

Если вы все еще хотите застрять с MySQL, вам необходимо реализовать блокировку, чтобы избежать многократной вставки в один и тот же URL. Вы можете взглянуть на эту документацию: https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/transactions-and-concurrency.html

Кроме того, вы можете (и должны) добавить уникальное ограничение в поле URL страницы. Это лучшая практика, поскольку вы не хотели, чтобы в вашей таблице было два одинаковых URL-адреса.