Москва, 2020
Пестерников Степан
Backend разработчик
• Работаю в Avito BX Geo
• GitHub: @pshopper
Slide 3
Slide 3 text
Москва, 2020
Go и Geo в Avito
• 12 сервисов на Go
• Хранилище гео-объектов на MongoDB
• Более 25000 запросов в секунду
Slide 4
Slide 4 text
Москва, 2020
Go и Geo в Avito
Slide 5
Slide 5 text
Москва, 2020
Go и Geo в Avito
Slide 6
Slide 6 text
Москва, 2020
Go и Geo в Avito
Slide 7
Slide 7 text
Москва, 2020
Немного теории
• Геоданные
• Полигоны
Slide 8
Slide 8 text
Москва, 2020
Геоданные
• Долгота
• Широта
• Высота
Slide 9
Slide 9 text
Москва, 2020
Полигон
Slide 10
Slide 10 text
Москва, 2020
Гео-поиск
Задачи:
• Рассчёт расстояние от точки до точки или
полигона
• Поиск ближайшего полигона или точки
• Попадание точки в полигон
Slide 11
Slide 11 text
Москва, 2020
Немного истории
MongoDB
Replica Set
Geo Queries
Bottleneck
6k connections
300 Mbps
Geo Queries
Geo Queries
…
PHP
PHP
PHP
Slide 12
Slide 12 text
Москва, 2020
Миграция на Go
Geo Queries
…
PHP
PHP
PHP
Go
PHP Go
MongoDB
Replica Set
RPC
RPC
Go
RPC
Geo Queries
Geo Queries
…
100 Connections
Slide 13
Slide 13 text
Москва, 2020
Что дальше? Новые проблемы?
• Поиск ближайшего полигона в MongoDB выполняется
более 500ms
• Задача проверки на попадание в полигон более 20
миллионов координат
• Запросы мимо кэша
• Задержки сети и точки отказа
• MongoDB не покрывает наши запросы по
функциональности
• Постоянное обновление геоданных
Slide 14
Slide 14 text
Москва, 2020
Geo Database & Libraries
• Redis
• Elastic
• Postgres
• Tile38 & BuntDB
• Go S2 Geometry
Slide 15
Slide 15 text
Москва, 2020
Tile38
• RealTime geofencing
• Redis протокол
• R-Tree индекс
• Поиск ближайшего (k-nearest neighbor algorithm)
Slide 16
Slide 16 text
Москва, 2020
S2 Geometry
• S2 Cells
• Shape Index
Slide 17
Slide 17 text
Москва, 2020
S2 Cells
Slide 18
Slide 18 text
Москва, 2020
S2 Cells
Slide 19
Slide 19 text
Москва, 2020
S2 Polygons
Slide 20
Slide 20 text
Москва, 2020
Go S2 Geometry vs MongoDB
• MongoDB использует S2 Geometry C++
• Неоптимальный алгоритм поиска ближайшего
полигона или точки
Slide 21
Slide 21 text
Москва, 2020
Неоптимальный алгоритм MongoDB
…
Точка Точка
…
…
…
Slide 22
Slide 22 text
Москва, 2020
Неоптимальный алгоритм MongoDB
Так как все Авито-
локации
сосредоточены в
полигоне России, то
при поиске из-за
пределов полигона,
алгоритм сводится к
«поиску полным
перебором»
Slide 23
Slide 23 text
Москва, 2020
Миграция на Go S2 Geometry
• Особенности работы и реализации
• Нагрузочное тестирование
• Сравнение с MongoDB
Slide 24
Slide 24 text
Москва, 2020
Особенности работы
• Проверка на вхождение в полигон через Shape
Index
• В Shape Index не портирован поиск ближайшего
полигона*
• Поиск ближайшего полигона на основе S2 Cells и
B-Tree индекса
*https://github.com/golang/geo/issues/59
Slide 25
Slide 25 text
Москва, 2020
Особенности реализации
• Координаты должны
идти по порядку в одном
направлении
• Не должно быть
повторяющихся
координат
• Обязательно проверять
валидность
• Возможно расширять
встроенный тип полигона
Slide 26
Slide 26 text
Москва, 2020
Нагрузочное тестирование
6 подов в k8s по 500 Mi Memory и 1 CPU
Slide 27
Slide 27 text
Москва, 2020
Особенности реализации
Построение Shape Index*
*Фикс - https://github.com/golang/geo/pull/65
Slide 28
Slide 28 text
Москва, 2020
Сравнение с MongoDB
3 дата-ноды MongoDB на железе по 8 Gb Memory и 8 CPU
Slide 29
Slide 29 text
Москва, 2020
В итоге
• Поиск ближайшего полигона ускорился в 60 раз
• Проверка на вхождение в полигон ускорилась в 500
раз
• Возможность держать нагрузку более 10000
запросов в секунду
• Гео-индекс хранится в памяти приложения
• Устранены задержки сети и точки отказа
Slide 30
Slide 30 text
Москва, 2020
В итоге
• Появились возможности проводить эксперименты
и АБ-тесты с полигонами
• Снизили трудозатраты на обновление геоданных
• Избавились от миграций