Я пытаюсь создать простое приложение для социальных сетей, начиная с серверной части.
Когда пользователь открывает приложение, будет отображен список пользователей на основе его / ее Географическое положение, возраст и пол.
Один пользователь был просмотрен, он больше никогда не будет показан.
Я использую Azure CosmosDB (реализация MongoDB) и кэш Redis для Azure для хранения документов.
Я сохраняю все пользовательские db в cosmosdb. Я запрашиваю идентификаторы пользователей на основе фильтров географических координат и предпочтений по возрасту и полу и ограничиваю результаты до 5000.
Я также применяю еще один фильтр, если пользователь уже просматривал фильтр. Я поддерживаю коллекцию, в которой для каждого пользователя все идентификаторы пользователей, которые он просматривал, будут сохранены как документ.
Впервые я получу 5000 идентификаторов из cosmosdb и помещу 4950 в кеш Redis (со сроком действия). Используя оставшиеся 50 идентификаторов, я получу пользователей из cosmosdb и верну их в качестве ответа на вызов API. Для последующих вызовов я получаю следующие 50 идентификаторов из кеша Redis, получаю этих пользователей и возвращаю их в качестве ответа.
Выборка 5000 пользователей требует времени, поскольку включает в себя вычисление геолокации и другую фильтрацию. Я создал образец базы данных пользователей, где в радиусе 100 миль насчитывается почти 2 миллиона пользователей, и я должен получить 100 000 пользователей в зависимости от моих предпочтений, то есть возраста и пола, если бы я не применил ограничение в 5000. Это займет около 25 секунд.
Применение лимита 5000 приведет к запуску запроса только в течение 1–1,5 секунды. Покупайте по мере того, как пользователи просматривают, то есть, когда фильтр Not-In (девять долларов) исключит эти 5000 идентификаторов, время в конечном итоге увеличится. Время, необходимое для получения из кеша, будет быстрым, но когда кеш будет исчерпан или истечет, и мы должны нажать cosmos db, чтобы запросить еще 5000 пользователей, это займет больше времени, поскольку количество пользователей, которых он уже просматривал, продолжает расти.
Формат времени в часах: мин: сек. Выполняется только для статистики производительности. Фактический запрос Api будет предоставлять 50 пользователей каждый раз (большую часть времени из кеша).
первый раз
Время, необходимое для получения 5000 совпадений, составляет 00: 00: 01.22.
Время, необходимое для установки Viewed Ids, составляет 00: 00: 00.06.
второй раз
Время, необходимое для получения 5000 совпадений, составляет 00: 00: 02.49.
Время, необходимое для установки Viewed Ids, составляет 00: 00: 00.67.
: :
Пятнадцатый раз
Время, необходимое для получения 5000 совпадений, составляет 00: 00: 23.05.
Время, необходимое для установки Viewed Ids, составляет 00: 00: 09.23.
Вопрос
Как можно улучшить архитектуру для повышения производительности? Как такие приложения, как Uber, Tinder и т. д., В которых используются вычисления геолокации пользователей, проектируют свое приложение? Есть ли лучший способ смоделировать проблему или смоделировать данные?
Любая помощь будет оценена по достоинству. Спасибо.
Поскольку вы уже касаетесь Redis, пробовали ли вы посмотреть, какова производительность Redis geo для вашего сценария? См. GEOADD и GEORADIUS[BYMEMBER][_RO].
@MohammadNikravesh - учтите, что ваш ответ может быть истолкован как очень агрессивный, например, вы кричите на кого-то за вопрос, который не соответствует правилам. Учитывая негативную репутацию, которую получает Stack Overflow в наши дни, возможно, выбрать другой подход?
@DavidMakogon, отметил, спасибо за совет
@Marc Gravell Еще не пробовал делать какие-либо вычисления на стороне Redis. Я попробую, если не слишком дорого.
@MohammadNikravesh Я спрашиваю, как можно улучшить производительность. Должен ли я моделировать свои данные по-другому или использовать другую технологию или подход?
@THECODER, конечно, единственный способ узнать, насколько это дорого (или нет) выяснить: это попробовать его с реалистичным объемом данных. Написание скрипта, который загружает Redis с соответствующими тестовыми данными, чтобы опробовать его, должно занять максимум 10 минут.





2 миллиона пользователей достаточно, чтобы начать иметь хорошую стратегию индексации, чтобы запросы к базе данных работали. Географические запросы создают уникальную проблему индексации, потому что это поиск по двум связанным переменным (а именно долготе и широте).
Там хорошее описание того, как сервер Microsoft SQL выполняет свой пространственный указатель здесь, которое также хорошо резюмирует проблему индексации в более общем плане.
Хотя я лично не использовал его, CosmoDB, похоже, теперь тоже имеет некоторую поддержку для этого. См. это и это.
Первое, что я хотел бы сделать, это немного переосмыслить ваши ожидания - просто нахождение 50 или 5000 (или любого другого п) ближайших элементов может потребовать длительного поиска, если поблизости нет совпадений (или даже если они есть), но если ваша база данных правильно проиндексировано, вы можете очень эффективно искать в пределах некоторого радиуса р точки, а затем сортировать эти результаты по расстоянию. Если у вас есть или ожидаете иметь большое количество координат, я бы посоветовал сделать это несколько раз, другими словами, поиск всех совпадений со 100 м, сортировка по расстоянию, а затем, если вам нужно больше, поиск всех совпадений в пределах 500 м и исключение те, которые вы уже видели, и т. д. до 10 или 25 км или в зависимости от того, что требует ваше приложение.
MongoDB имеет довольно эффективный индекс, доступный для геопространственных координат (в основном карта мира, разделенная на деревья B +). Запрос '$near' позволяет вам указывать как минимальное, так и максимальное расстояние, а также сортировать по расстоянию по умолчанию, так что это очень удобно для такого многоуровневого поиска на основе расстояния. Вам нужно будет отформатировать свои координаты (как в БД, так и в запросе) как объекты GeoJSON Point, если они еще не были.
Спасибо за ответ. Я уже использую индекс 2dsphere. Вышеупомянутая статистика включает его. Тем не менее, производительность может быть низкой, если он просмотрел около 7500 пользователей. На запрос потребуется 23 секунды.
Похоже, ваша проблема не в вычислении местоположения, а в исключении элементов на основе растущего списка уже просмотренных идентификаторов. Однако вы можете использовать местоположение / расстояние, чтобы лучше разделить пространство поиска, позволяя пространственному индексу выполнять большую часть работы за вас, вместо выполнения (возможно, линейного) поиска по идентификаторам 5000 * n.
Скажите, пожалуйста, что именно вы хотите? Не спрашивая архитектуры !!