Redis GEO 是什么?如何实现附近地点查询,精度有什么限制?
下面是一段教学用的模拟面试。
🧑💻 面试官:怎样用 Redis 查附近五公里的地点?
🙋♂️ 我:把经纬度存进去,按距离取前十个。
🧑💻 面试官:经度和纬度哪个在前?COUNT 10 ANY 能保证最近十个吗?某个地点已经关闭,GEO 会帮你过滤吗?
🙋♂️ 我:空间范围和业务状态还得分开处理。
🧑💻 面试官:地图道路绕行很长,GEO 距离能当成导航路程吗?
GEO 解决的是地理位置范围查询。距离模型、结果排序和业务可用状态,仍然是不同的问题。
面试速答(60 秒版)
Redis GEO 把成员的经纬度编码到有序集合中,利用空间编码范围筛选候选,再检查查询形状与距离条件。
GEOADD 写入时是经度在前、纬度在后;GEOSEARCH 可以按圆形或矩形查询,并选择按距离排序和返回距离等信息。
查询最近若干个结果,需要注意排序与 COUNT 的含义。COUNT ANY 可以提前结束搜索,不保证得到全范围内真正最近的那些结果。
GEO 使用球面近似距离,不是道路距离,也不适合直接承担高精度测绘要求。营业状态、权限和坐标更新时间等业务信息还需要独立维护与校验。

知识点详解:从地图上的点,到真正可展示的结果
经纬度怎样变成可以检索的成员?
假设地点 A 有经纬度和一个稳定的地点 ID。GEOADD 将坐标与 ID 写入一个 GEO 键,该键底层是有序集合,分值编码了空间位置信息。
顺序是 longitude、latitude,也就是经度、纬度。交换顺序可能报范围错误,也可能得到一个合法却完全错误的位置。
Redis 对可索引纬度有边界,不覆盖极点附近所有区域;坐标系也要由应用统一。来自不同地图来源的坐标,不能不加判断地混在一起。GEOADD 文档
查询不是把所有地点都算一遍距离
空间编码帮助系统把查询区域转成相关编码范围,先找候选,再排除不满足形状或距离条件的地点。
因此效率与附近区域的密度、范围大小和结果要求有关。不能因为最后只显示十个点,就保证服务端只检查十个点。
下面是原生命令示意,不依赖 TypeScript 或 Python 客户端的参数封装:
GEOSEARCH places FROMLONLAT 121.47 31.23 BYRADIUS 5 KM ASC COUNT 10 WITHDIST
示意中的坐标只是查询输入,不代表任何真实地点数据或已运行结果。
最近十个,和任意十个,有什么区别?
ASC 表示按距中心的距离从近到远排列。COUNT 限制返回数量;加上 ANY 则允许在找到足够成员后提前结束,不保证它们是整个范围内最近的成员。
即便提前找到的结果最后又被排序,也只是这批已找到结果之间的顺序,不能推出它们等于全范围的最近十个。GEOSEARCH 文档
附近推荐可以按产品需要接受这种取舍,但“最近”有明确承诺时,不能悄悄采用不保证最近的配置。

地理距离为什么不等于导航距离?
Redis 采用球面近似模型计算地理距离,坐标编码也有有限精度。它不会考虑道路、河流、单行线、地形或实时交通。
隔河很近的两个点,开车可能需要绕远。GEO 可以用于地理范围初筛,再结合路线服务和业务条件,但不能把它输出的距离直接标成预计行车路程。
精度要求很高时,应选择符合相应测地模型与误差要求的系统,而不是只增加小数位展示。
地点的位置和营业状态怎么维护?
GEO 成员 ID 可以关联数据库中的地点详情。查到附近候选后,还要过滤关闭、无权限或数据过期的地点。
如果先取十个再过滤,最终可能不足十个。可根据需要取更多候选、继续查询或采用更适合组合过滤的空间数据库方案,不能假装 GEO 内置了所有业务谓词。
更新位置可以更新同一成员;删除成员可使用 ZREM。通常的 GEO 命令不会自动为每个地点附加业务过期逻辑,移动对象需要额外维护更新时间和清理策略。
面试官继续追问
为什么不直接用普通 ZSET 存距离?
距离取决于查询中心。换一个中心,同一地点的距离就变了,不能用一个固定距离分值解决所有位置查询。
GEO 能查询任意复杂多边形吗?
它不是完整的 GIS 引擎。圆形、矩形查询之外的复杂空间关系,应按需求评估专门系统。
查到结果就能展示了吗?
还要核对坐标新鲜度、地点状态和用户权限。空间命中只说明符合相应位置条件。
面试速记卡
- 写入顺序:经度在前,纬度在后。
- 底层方式:有序集合保存空间编码,筛选后检查范围。
- 最近结果:ASC 与 COUNT 按需求使用,ANY 不保证全局最近。
- 距离限制:球面近似地理距离,不是道路距离。
- 业务边界:状态、权限和更新时间独立维护。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →