Redis GEO 实现 LBS 搜索:附近的人

介绍

早在15年的 Redis 3.2 开始就已提供了 GEO 相关方法,可用来实现 LBS 搜索:

  • geoadd:增加某个地理位置的坐标
  • geopos:获取某个地理位置的坐标
  • geodist:获取两个地理位置的距离
  • georadius:根据给定地理位置坐标获取指定范围内的地理位置集合。
  • georadiusbymember:根据给定地理位置获取指定范围内的地理位置集合
  • geohash:获取某个地理位置的 geohash 值

GEOADD 添加位置

GEOADD key longitude latitude member-x [longitude latitude member-y ...]

GEOPOS 获取位置

GEOPOS key member-x [member-y ...]

GEODIST 计算两个成员的距离

GEODIST key member-x member-y m|km|ft|mi

GEORADIUS 半径搜索、获取指定范围内的成员

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [ASC|DESC] [COUNT count]

参数说明

  • radius 搜索半径
  • m/km/ft/mi 指定的是计算范围时的单位
  • WITHCOORD 将位置的经纬度一并返回
  • WITHDIST 将位置与中心点之间的距离一并返回
  • 在默认情况下,GEORADIUS 和 GEORADIUSBYMEMBER 的结果是未排序的,ASC 表示按距离从近到远排序,DESC 表示从远到近;
  • COUNT 限定返回的记录条数

缺点

  1. 无法分页查询
  2. 在默认情况下,GEORADIUS 命令会返回所有匹配的位置元素。虽然可以用 COUNT 选项去获取前 N 个匹配元素,但是因为命令在内部可能会需要对所有被匹配的元素进行处理,所以在对一个非常大的区域进行搜索时,即使用了 COUNT,执行也会非常慢,但起码对于减少网络带宽来说是非常有用的。

实测结果

用 GEORADIUS 和 GEORADIUSBYMEMBER 查询 600w 条数据并计算距离并排序,耗时 80ms 左右,效率非常的高。

GEORADIUSBYMEMBER

相当于 GETPOS + GEORADIUS 二合一。

GEOHASH

获取某个地理位置的 GEOHASH 值。GEOHASH 是将二维的经纬度转换成字符串 hash 值的算法。

GEOHASH key member-x [member-y ...]

实现原理

  1. 使用 GeoHash 保存地理位置的坐标。
  2. 使用有序集合(zSet)保存地理位置的集合。

GeoHash 是什么?

详情点击:GeoHash 核心原理解析

GeoHash 的思想是将二维的经纬度转换成一维的字符串,GeoHash 有以下三个特点:

  1. 字符串越长,表示的范围越精确。编码长度为8时,精度在19米左右,而当编码长度为9时,精度在2米左右。
  2. 字符串相似的表示距离相近,利用字符串的前缀匹配,可以查询附近的地理位置。这样就实现了快速查询某个坐标附近的地理位置。
  3. GeoHash 计算的字符串,可以反向解码出原来的经纬度。

参考文章