Ответ
В проекте мы использовали встроенный геопространственный индекс Redis, который реализован поверх Sorted Sets (ZSET). Координаты (широта, долгота) кодируются в 52-битный geohash, который сохраняется как числовой score в ZSET.
Ключевые команды:
GEOADD— добавление точки с именем и координатами.GEORADIUS/GEOSEARCH— поиск точек в заданном радиусе.
Пример на C# (StackExchange.Redis):
var db = redis.GetDatabase();
// Добавление локации
await db.GeoAddAsync("locations",
new GeoEntry(longitude: 37.6176, latitude: 55.7558, member: "Moscow"));
// Поиск всех точек в радиусе 50 км от координат
var nearby = await db.GeoRadiusAsync("locations", 37.62, 55.75, 50, GeoUnit.Kilometers);
Преимущества подхода:
- Молниеносный поиск по радиусу за O(log N).
- Минимальная настройка — используется штатный функционал Redis.
- Легко масштабируется и реплицируется.
Ограничения:
- Нет поддержки сложных геометрических операций (полигоны, пересечения, объединения).
- Точность ограничена geohash (погрешность ~1–2 см).
- Нет полноценной поддержки CRS (систем координат).
Для сложных GIS-задач (работа с полигонами, расчёты площади) мы подключали PostGIS или использовали библиотеку NetTopologySuite в памяти приложения.