В каком формате хранились геоданные в 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 см).
  • Нет полноценной поддержки 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 — это для быстрого "найди всё рядом", а для остального есть другие инструменты, и это нормально.