Ответ
В проекте мы использовали встроенный геопространственный индекс 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 в памяти приложения.
Ответ 18+ 🔞
Давай разберём эту штуку с геоиндексами в Redis, чтоб всё стало понятно, как два пальца обоссать.
В общем, мы в проекте юзали встроенную в 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 см, но для большинства задач — норм.
- Систем координат, кроме WGS84, тут нет. Если тебе нужно что-то экзотическое — будет боль.
Поэтому, когда задачи пошли серьёзные — типа расчёта площади полигонов или сложных пространственных запросов — мы брали в работу PostGIS или ворочали полигоны прямо в памяти приложения через NetTopologySuite. Redis — это для быстрого "найди всё рядом", а для остального есть другие инструменты, и это нормально.