Как реализовать сценарий сохраненных поисков

что такое save-search?

Сохранить - это механизм, по которому пользователи не находят желаемых результатов в расширенном поиске и просто нажимают "Сохранить мои критерии поиска снизу", и мы сохраняем критерии поиска, и когда соответствующие данные публикуются на веб-сайте, мы сообщаем пользователю "эй пользователь, элемент (s) ты искал, существует, теперь приходи и посети его ".

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

У нас расширенный поиск, и нам не нужно реализовывать новый поиск, нам нужен хороший сценарий производительности для реализации механизма сохраненного поиска.

У нас есть веб-сайт, на котором пользователи публикуют около 120000 сообщений в день, и мы собираемся реализовать сценарий SAVED SEARCH (что-то вроде этого, что делает https://www.gumtree.com/), это означает, что пользователи используют расширенный поиск, но они не находят желаемый контент и просто хотят сохранить критерии поиска, и если на сайте будут какие-либо результаты, мы сообщим им об этом с уведомлением.

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

предлагаемые решения, но не лучшие

  • Одним из быстрых решений является сохранение сохраненных поисков в сохраненном поисковом индексе в Elastic, а затем выполнение cronjob, который для всех элементов сохраненных поисков получает результаты из posts-index- Elastic, и, если есть какой-либо результат, помещает запись в RabbitMq для уведомить эквивалентного пользователя.

  • когда пользователь публикует элемент на веб-сайте, мы проверяем его с помощью существующих сохраненных поисков в сохраненном поисковом индексе в Elastic и, если это совпадает, мы помещаем запись в RabbitMq,(главная проблема этого метода в том, что он может быть сопоставлен с огромным количество сохраненных поисков в каждом сообщении, вставленном на сайт).

Мое большое беспокойство связано с масштабом и производительностью, я буду благодарен, если вы поделитесь со мной вашим опытом и идеями по этой проблеме

Моя оценка по шкале

  • Срок годности сохраненного поиска - три месяца.
  • не менее 200000 сохраненных поисков в день
  • Итак, у нас есть 9 000000 активных записей.

Я буду признателен, если вы поделитесь своим мнением со мной

* просто к сведению ** - у нас также есть RabbitMQ для наших заданий в очереди - наши ES-серверы достаточно хороши с 64 ГБ ОЗУ

4 ответа

Cron работа - Нет. Постоянная работа - да.

Зачем? По мере масштабирования или всплесков активности работа cron становится проблематичной. Если задание cron на 09:00 выполняется слишком долго, оно будет конкурировать за ресурсы с экземпляром 10:00; это может привести к катастрофе.

С другой стороны, если задание cron завершается "рано", то активность колеблется между "занятым" (задание cron выполняет какие-то действия) и "не занятым" (cron завершил работу, а не время для следующего вызова).

Поэтому вместо этого я предлагаю работу, которая постоянно проходит через все "хранимые запросы", выполняя их по одному за раз. Когда он заканчивает список, он просто начинается заново. Это полностью исключает мои жалобы на cron и обеспечивает автоматическую "эластичность" для обработки времени занятости / отсутствия занятости - сканирование замедляется или соответственно ускоряется.

Когда задание заканчивается, список начинается заново в списке. То есть он работает "навсегда". (Вы можете использовать простое задание cron в качестве "keep-alive" монитора, который перезапускает его в случае сбоя.)

Хорошо, "одна работа", переоценка "по одной", вероятно, не самая лучшая. Но я не согласен с использованием механизма очередей. Вместо этого у меня было бы небольшое количество процессов, каждый из которых воздействовал бы на некоторый кусок хранимых запросов. Есть много способов: захватить и заблокировать; дай мне сто работать; по модулю N; и т.д. У каждого есть свои плюсы и минусы.

Поскольку вы уже используете Elasticsearch и подтвердили, что создаете что-то вроде Google Alerts, самым простым решением будет Elasticsearch Percolator.

Из официальной документации Percolator полезен, когда:

Вы используете платформу оповещения о ценах, которая позволяет покупателям, ориентированным на цену, указывать правило типа "Я заинтересован в покупке определенного электронного гаджета и хочу получать уведомление, если цена гаджета упадет ниже $X у любого поставщика в течение следующего месяца"., В этом случае вы можете очистить цены поставщиков, вставить их в Elasticsearch и использовать его функцию обратного поиска (Percolator) для сопоставления ценовых движений с запросами клиентов и, в конечном итоге, после того, как совпадения будут найдены, отправлять предупреждения клиентам.

Я не могу сказать много, когда речь заходит о производительности, потому что вы не предоставили ни одного примера ваших запросов, но в основном потому, что мои выводы противоречивы.

Согласно этому сообщению ( https://www.elastic.co/blog/elasticsearch-queries-or-term-queries-are-really-fast), запросы Elasticsearch должны быть способны достигать 30000 запросов в секунду. Однако, этот вопрос без ответа (производительность Elasticsearch percolate) сообщил о мучительно медленных 200 запросах в секунду на сервере с 16 процессорами.

Без дополнительной информации я могу только догадываться, что причина кроется в проблемах конфигурации, поэтому я думаю, что вам придется попробовать кучу разных конфигураций, чтобы получить максимально возможную производительность. Удачи!

Этот ответ был написан без истинного понимания последствий "сохраненного поиска". Я оставляю это здесь как обсуждение связанной проблемы, но не как решение "сохраненного поиска". - Рик Джеймс

Если вы сохраняете только "запрос", я не вижу проблемы. Я предполагаю, что вы сохраняете как запрос, так и "набор результатов"...

Один "сохраненный поиск" в секунду? 2,4 млн рядов? Просто повторите поиск, когда это необходимо. Система должна быть в состоянии справиться с такой небольшой нагрузкой.

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

На самом деле сохранение результирующего набора и возможность его воспроизведения включает в себя (1) сложность в вашем коде, (2) накладные расходы на кеширование, ввод-вывод и т. Д., И т. Д.

Какое среднее количество раз пользователь просматривает один и тот же поиск? Из-за только что упомянутых накладных расходов я подозреваю, что среднее число раз должно быть больше 2, чтобы оправдать накладные расходы.

Итог... Это пахнет как "преждевременная оптимизация". рекомендую

  1. Создайте сайт без сохранения результатов.
  2. Стресс-тест, чтобы увидеть, когда он сломается.
  3. Работайте над оптимизацией медленных частей.

Что касается RabbitMQ - "Не ставь в очередь, просто сделай это". Стоимость постановки в очередь и снятия с очереди составляет (1) увеличение задержки для пользователя и (2) увеличение накладных расходов в системе. Выгода (в вашем среднем масштабе) минимальна.

Если вы столкнулись с проблемами масштабирования, подумайте

  • Переместите клиентов на другой сервер - подальше от базы данных. Это даст вам некоторое масштабирование, но не 2x. Идти дальше...
  • Используйте репликацию: один мастер + много ведомых только для чтения - и выполняйте запросы на подчиненных. Это дает вам практически неограниченное масштабирование в базе данных.
  • Есть несколько веб-серверов - практически неограниченное масштабирование в этой части.

Я не понимаю, почему вы хотите использовать сохраненный поиск... Во-первых: вы должны оптимизировать сервис, чтобы использовать как можно меньше сохраненного поиска.

Вы сделали что-нибудь с сервером ES? (Что вы можете себе позволить), так что

  1. Вы оптимизировали сервер elasticearch? По умолчанию он использует 1 ГБ оперативной памяти. Лучшее решение - дать ему половину оперативной памяти, но не более 16 ГБ (если я помню. Проверьте документ)
  2. Насколько мощна машина ES? Он любит ядро ​​вместо MHZ.
  3. Сколько узлов ES у вас есть? Вы всегда можете добавить другую машину, чтобы получить результаты быстрее.
  4. В моем случае (ES 2.4) сервер через несколько дней замедляется, поэтому я перезагружаю его один раз в день.

И следующее:

  1. Почему вы хотите запускать задания каждые полчаса? Если вы уже используете cron, запускайте каждую минуту, и вы указываете, что запрос выполняется. С другой пост у вас есть лучшее решение и объяснение.
  2. Почему вы отделяете результат от запроса?
  3. Не забудьте стандартизировать запрос, чтобы изменить порядок параметров, а не форсировать новый запрос.
  4. Почему вы хотите использовать MySQL для хранения результатов? Лучшая база данных типа документа, например Elasticsearch xD,

Я предлагаю вам:

  1. Оптимизируйте структуру ES - выберите правильные токенизаторы для полей.
  2. Используйте асинхронную загрузку результатов - например, WebSocket + Node.js
Другие вопросы по тегам