Как организовать архитектуру для подписки по ключевым словам (как пример, Avito)?

Ситуация такая:
Имеется:
1) БД Postgres, в которой хранятся подписки пользователей ~50000 запросов. Запросы вида: Автомобили, Москва, пробег до 100 тыс., в описании есть "зимняя резина", "в родной краске".
2) Кластер ElasticSearch, в котором часто появляются новые документы - объявления. До 500 в минуту.

Задача: организовать рассылку по новым объявлениям как в avito, auto.ru.

Что происходит сейчас:
За минуту загружается ~500 новых объявлений, кладем их в ElasticSearch, и раз в минуту запускаем процесс проверки, какому пользователю какое объявление подходит. Т.е. формирую 50000 запросов к ElasticSearch с заданными id-шниками новых записей (потому что в запросах юзеров есть полнотекст, которым и занимается ES), и потихоньку, по 500 за раз выполняю их на кластере ElasticSearch. Некторые объявления удается отфильтровать на backend, например, если регион не подходит, но запросов все-равно очень много. Соответсвенно, эластик вешается от такого количества полнотекстовых запросов, и поиск по сайту начинает страшно тормозить.

Вид запросов условно такой:
1) Найти среди 500 новых объявлений те, в которых встречается словосочетание "цвет белый", в гороне Казань
2) Найти среди 500 новых объявлений те, в которых встречается "зимняя резина" или "полный электропакет", в городе Москва
........
и таких еще 49000

Есть какие-то идеи как лучше организовать такое решение с рассылкой? Или кто поделится опытом, как устроена система принятия решения, подходит ли документ пользователю или нет, у гигантов, как avito, auto.ru?
  • Вопрос задан
  • 2133 просмотра
Решения вопроса 2
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
1. Выделить из запроса сущности (имена существительные): можно использовать это
2. Проверить по заранее подготовленному словарю синонимов и унифицировать всё, что имеет неточности и является синонимом.
3. Делаем привязку тегов текущего объявления к ОБЩЕМУ списку тегов объявлений всей системы.
4. Под объявлением отображаем только 5-6 тэгов, с максимальным количеством объявлений внутри каждого тега (кол-ва привязанных объявлений к этому тегу) по всей системе.
5. В очередь пользователя для отправки - помещаем ID объявлений по его подписке: тэги и т.д.
6. Как только пул новых объявлений превышает пороговое значение - делаем рассылку. Например, каждые 30 новых из общей очереди пользователя:
if($newItemsForUser>=30) {
   /* 
      команда запроса инициализации рассылки
      например, команда через API микросервису
   */
}
Ответ написан
Sanasol
@Sanasol
нельзя просто так взять и загуглить ошибку
Думаю логично для подписок использовать модель pubsub в любой реализации.
И соответственно делать рассылку сразу после создания каждого объявления.
Точнее добавлять объявления в некий пул для рассылки, и как только наберется N количество, отправлять рассылку.

  1. Создается объявление
  2. Попадает в очередь для парсинга
  3. Парсер вычленяет из объявления ключевые слова по базе подписок.
  4. Если ключевые слова находятся, то объявление отправляется в соответствующие каналы(пулы) для рассылки
  5. После того как пул набирает N количество объявлений - делается рассылка.


В итоге должно получиться что-то вроде того что нужно.

"Продам гараж в Москве, белый"
Парсер нашел: москва, белый гараж
Объявление попало в каналы: москва, белый гараж.
И после того как наберутся остальные объявления либо когда пройдёт N времени, очередь рассылается подписчикам этих двух каналов и очищается.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
dimonchik2013
@dimonchik2013
non progredi est regredi
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы