В современном мире высоких технологий рост объема данных и потребностей пользователей ставит серьезные вызовы перед компаниями, предоставляющими сервисы доставки продуктов и еды. Одним из ярких примеров масштабирования поисковых систем является Uber Eats — платформа, которая справляется с миллиардами ежедневных запросов, сохраняя при этом высокую скорость и релевантность результатов. Как именно Uber Eats смогла добиться такого результата, стоит разобраться подробнее. Основная сложность, с которой столкнулись инженеры компании, заключалась в необходимости масштабировать поиск не только по количеству запросов, но и по разнообразию данных. Изначально речь шла о ресторанах, однако со временем платформа стремительно расширилась, добавив новые вертикали, включая продуктовые магазины, розничные точки и даже доставку посылок.
Такое эволюционное развитие существенно усложнило архитектуру поиска. Для каждого пользователя результаты поиска должны оставаться персонализированными, соответствующими его вкусовым предпочтениям и географическому расположению. В Uber Eats поисковая система должна справляться с запросами из разных частей мира, учитывать часовые пояса, плотность населения, а также особенности локальной доставки. Именно эти аспекты стали главными препятствиями на пути к масштабированию. Чтобы решить эти задачи, команда Uber Eats разработала многоступенчатый конвейер обработки запросов, который включает этапы понимания запроса, индексирования, первоначального выбора кандидатов, первой и второй сортировки, а также дополнительного обогащения данных.
Такой системный подход позволил не только оптимизировать скорость, но и повысить качество результатов. Особое внимание было уделено процессу индексирования. Данные из разных источников, включая рестораны и магазины, сначала проходят пакетную обработку с использованием кластерных вычислений, что позволяет подготавливать большие объемы информации для хранения в формате, удобном для поиска. Параллельно реализованы механизмы потокового обновления данных, обеспечивающие моментальное отражение изменений, например, новых товаров или смены цен. sharding, или шардирование, оказалась ключевой концепцией для масштабирования поиска.
Uber Eats применяет две основные стратегии: по широте и по географическим гексагональным зонам с помощью собственного инструмента H3. Шардирование по широте разбивает карту мира на горизонтальные полосы, что позволяет равномерно распределять нагрузку по серверам с учетом часовых поясов. Этот подход хоть и прост, но вызывает проблемы в густонаселённых местах из-за неравномерного распределения данных. Для решения этих проблем внедрено гексагональное шардирование, основанное на разбиении карты на шестиугольные регионы. Такая модель позволяет более точно определять зоны доставки и обеспечивает равномерное распределение нагрузки на сервера.
Кроме того, двустороннее дублирование данных на границах шард помогает избежать потери релевантных результатов при выполнении поисковых запросов вблизи границ регионов. Также важную роль сыграла оптимизация структуры индекса. Для ресторанного сегмента документы упорядочиваются по городу, ресторану и товарам внутри него, что ускоряет фильтрацию и сжатие данных. В категорию продуктов питания отнесён другой подход к организации, где упор сделан на ограничение показа предметов от одного продавца, чтобы избежать монополизации результатов и обеспечить большее разнообразие. Внедрение умной индексации с учётом оценки времени доставки (ETA) стало настоящим прорывом.
Ранее поиск основывался исключительно на географическом расстоянии, но расстояние не всегда коррелировало с реальным временем доставки. Uber Eats ввела ранжирование по диапазонам ETA с дублированием магазинов в нескольких категориях, что позволило повысить качество соответствия запросу и сократить задержки. Проблема резкого увеличения количества кандидатов для ранжирования была решена благодаря разделению запросов по ETA-бucket’ам и параллельной обработке на разных шардовых срезах. Это позволило сохранить низкую латентность и одновременно повысить полноту поиска. Такие технологические решения позволили масштабировать систему, не жертвуя качеством пользовательского опыта.
Для ранжирования результатов применяются два этапа. Первый быстрый фильтр ориентирован на оперативное отсеивание неподходящих вариантов и сохранение широты результата. Второй же этап учитывает множество факторов, включая персональные предпочтения пользователя, историю заказов, время суток и эффективность товаров для платформы. Такая многоуровневая система поднимает релевантность рекомендаций на новый уровень. Кроме того, Uber Eats внедряет механизмы приоритетной обработки обновлений для критичных изменений, связанных с ценой или доступностью, чтобы данные в поиске всегда оставались актуальными.
Система обмена сообщениями через Kafka обеспечивает надежность и масштабируемость передачи информации. Важной составляющей успеха является хорошая наблюдаемость и мониторинг. Выявляя узкие места и аномалии в режиме реального времени, команда может быстро реагировать и улучшать как индексирование, так и процесс поиска в целом, что крайне важно при обработке миллиардов запросов ежедневно. В итоге Uber Eats сумела построить масштабируемую, отказоустойчивую и высокопроизводительную поисковую систему, которая справляется с возрастающей нагрузкой и постоянно меняющимися бизнес-требованиями. Ключевыми факторами успеха стала комплексная архитектура, интеллектуальное гео-шардирование, адаптивная индексация с учетом времени доставки и многократный этап ранжирования результатов.
Применение подобных передовых подходов не только помогает обеспечить пользователям максимально релевантные и быстрые результаты, но и создает конкурентное преимущество на рынке доставки продуктов и еды. История Uber Eats служит замечательным примером того, как правильный выбор архитектуры и технологий способен справиться с самыми серьезными вызовами масштабируемости.