Я использую нишевый продукт для поиска, который работает с поисковым роботом. Текущий сканер - это один рабочий (PHP Laravel), который просматривает URL-адреса и помещает результаты в систему эластичного поиска. Система постоянно выполняет повторное сканирование найденных URL-адресов с интервалом в X миллисекунд.
Это сослужило мне хорошую службу, но с появлением новых крупных клиентов поисковый робот достигнет своих пределов. Мне нужно преобразовать систему в распределенный краулер, чтобы ускорить сканирование. Проблема заключается в сочетании спецификаций ниже.
Система должна придерживаться следующих 2 правил:
- несколько рабочих (проблемы с параллелизмом)
- переменный лимит скорости для каждого клиента. Мне нужно быть уверенным, что система не сканирует клиент X чаще одного раза в X миллисекунд.
Что я пробовал:
Я попытался поместить URL-адрес в таблицу MySQL и позволить рабочим запрашивать URL-адрес для сканирования на основе временных меток last_crawled_at в таблице клиентов и URL-адресов. Но MySQL не любит одновременную работу нескольких рабочих, и я получаю всевозможные тупики.
Я попытался поместить URL-адрес в движок Redis. У меня это вроде как работает, но только с Lua-скриптом, который проверяет и устанавливает истекающий ключ для каждого обслуживаемого клиента. Все это кажется хакерским.
Я думал о заполнении обычной очереди, но это нарушит правило номер 2, так как я не могу быть на 100% уверен, что рабочие могут обрабатывать очередь «в реальном времени».
Кто-нибудь может объяснить мне, как это делают большие мальчики? Как мы можем сделать так, чтобы несколько процессов запрашивали большой / массивный список URL-адресов на основе нескольких критериев (например, ограничение скорости клиента) и удостоверились, что мы передаем URL-адрес только 1 работнику?
В идеале нам не понадобится другая база данных, кроме Elastic, со всеми доступными / найденными URL-адресами, но я не думаю, что это возможно?