适用版本:Redis 7.2.x
一、什么是 GEO
GEO 是 Redis 提供的一组地理位置能力,用来存储和计算 经纬度坐标,并支持常见的地理查询需求,例如:
- 附近的人
- 附近的门店
- 两地之间的距离
- 某个区域内有哪些位置点
从使用方式上看,GEO 像是一种独立能力;但从底层实现来看,它其实是 基于 Sorted Set(有序集合)实现的地理位置索引方案。
这意味着:
- 每个成员对应一个地理位置
- Redis 会把经纬度编码成可排序的值
- 再借助有序集合完成范围检索
因此,GEO 适合做轻量级、实时性强的地理检索场景,而不是复杂 GIS 系统的替代品。
二、GEO 的核心原理
1. 经纬度不是直接拿来排序的
如果只把经度、纬度原样存进去,是很难直接做“附近搜索”的。因为“空间上的近”不等于“数值上的简单区间近”。
Redis 的 GEO 方案会先对经纬度进行编码,把二维坐标映射为一个可排序的整数值,再利用 Sorted Set 的 score 或排序能力来组织数据。
2. 底层依赖空间编码思想
Redis GEO 的核心思想可以理解为:
- 把地球上的位置切成网格
- 相近位置编码后也尽量接近
- 通过范围扫描找到候选点
- 再结合真实距离做精确过滤和排序
因此它兼顾了:
- 写入效率
- 附近检索效率
- 距离计算能力
3. 本质仍是“点数据检索”
GEO 特别适合处理“点”的位置问题,比如用户、骑手、门店、仓库,而不擅长:
- 多边形地理围栏
- 复杂路线规划
- 行政区边界分析
- 专业地图渲染
也就是说,GEO 更像“坐标附近检索工具”,而不是完整地图系统。
三、GEO 适用场景
1. 附近的人
社交类应用中常见需求:
- 显示我附近 5 公里内的用户
- 按距离排序展示附近的人
2. 附近门店/POI 检索
例如:
- 查找 3 公里内的便利店
- 查询当前定位周边的服务网点
- 找到最近的仓库或站点
3. 距离计算
例如:
- 计算用户与门店的距离
- 计算骑手与商家的距离
- 计算两个站点之间的直线距离
4. 配送或调度的候选筛选
在复杂调度系统中,GEO 常用于第一步粗筛:
- 先找附近若干候选点
- 再结合业务规则做二次筛选
四、常用命令与示例
Redis 7.2.x 中,GEO 常用命令主要包括 GEOADD、GEODIST、GEOSEARCH、GEOHASH、GEOPOS 等。
1. GEOADD:添加地理位置
先加入几个城市坐标:
GEOADD city:cn 116.405285 39.904989 beijing
GEOADD city:cn 121.472644 31.231706 shanghai
GEOADD city:cn 113.264385 23.129112 guangzhou
GEOADD city:cn 114.057868 22.543099 shenzhen
命令格式为:
GEOADD key longitude latitude member
注意顺序是:
- 先经度
longitude - 再纬度
latitude
很多初学者最容易把这两个参数写反。
2. GEOPOS:查看成员坐标
GEOPOS city:cn beijing shanghai
可以返回成员当前保存的经纬度。
3. GEODIST:计算两点距离
GEODIST city:cn beijing shanghai km
GEODIST city:cn guangzhou shenzhen km
单位可以是:
m:米km:千米mi:英里ft:英尺
这个命令适合快速计算两点直线距离。
4. GEOHASH:获取位置编码
GEOHASH city:cn beijing shanghai
返回位置编码字符串。平时业务中直接使用不算太多,但它有助于理解 GEO 的底层编码思想。
5. GEOSEARCH:按圆形范围搜索
查询北京附近 1500 公里内的城市:
GEOSEARCH city:cn FROMLONLAT 116.405285 39.904989 BYRADIUS 1500 km WITHDIST ASC COUNT 10
这个命令表示:
- 从给定经纬度出发
- 查找半径 1500 公里范围内的位置
- 返回距离信息
- 按距离升序排序
- 最多返回 10 条
6. GEOSEARCH:以成员为中心搜索
以 beijing 为中心找附近城市:
GEOSEARCH city:cn FROMMEMBER beijing BYRADIUS 1500 km WITHDIST WITHCOORD ASC COUNT 10
这个写法在业务里很常见,因为很多时候你已经有一个中心点成员。
7. GEOSEARCHSTORE:把搜索结果保存下来
GEOSEARCHSTORE city:near:beijing city:cn FROMMEMBER beijing BYRADIUS 1500 km ASC COUNT 10
这样可以把结果存入新的 key,方便后续复用。
五、一个典型案例:附近门店查询
假设有一批门店坐标,需要实现“查看我附近 3 公里门店”的功能。
1. 设计 key
store:geo:beijing
2. 写入门店位置
GEOADD store:geo:beijing 116.397128 39.916527 store:001
GEOADD store:geo:beijing 116.410000 39.920000 store:002
GEOADD store:geo:beijing 116.430000 39.900000 store:003
3. 根据用户当前位置查询附近门店
GEOSEARCH store:geo:beijing FROMLONLAT 116.405285 39.904989 BYRADIUS 3 km WITHDIST WITHCOORD ASC COUNT 20
返回结果中可以带上:
- 门店 ID
- 与用户的距离
- 门店坐标
然后在应用层再根据门店营业状态、库存、配送范围做二次过滤。
六、GEO 和 Sorted Set 的关系
理解 GEO 时,一个常见问题是:为什么说它基于 ZSet?
原因是:
- Redis GEO 的底层存储就是有序集合
- 地理位置会被转换成某种可排序的编码值
- 成员名称仍然是 member
所以如果你对 Sorted Set 已经熟悉,就更容易理解 GEO 的能力边界。
但要注意:
- 不建议直接手工修改其底层排序值
- 应优先使用 GEO 专用命令维护数据
七、GEO 的优点
1. 使用简单
相比引入专业地图数据库或空间索引系统,Redis GEO 的上手门槛非常低,几个命令就能完成附近检索。
2. 适合高频实时查询
像“附近的人”“附近门店”这类高频查询,Redis 可以提供很好的实时响应能力。
3. 可与 Redis 其他结构组合使用
例如:
- GEO 存坐标
- Hash 存门店详情
- Set 存门店标签
- Stream 记录位置变更事件
组合起来可以搭出完整业务方案。
八、使用 GEO 时的注意事项
1. 参数顺序一定是“经度在前,纬度在后”
这是最常见的错误之一。
正确写法:
GEOADD key longitude latitude member
不是纬度在前。
2. 距离是球面距离的近似计算,不等于路线距离
GEODIST 或 GEOSEARCH 给出的通常是地理直线距离或基于球面模型的距离近似值,不代表真实驾车距离、步行距离。
如果业务需要路线规划,应该接入地图服务,而不是只依赖 Redis GEO。
3. 更适合中小规模附近检索,不是专业 GIS 引擎
GEO 很适合“找附近点”,但不适合:
- 多边形包含判断
- 地理围栏复杂运算
- 行政区边界分析
- 复杂空间聚合
这类需求需要更专业的地理空间系统。
4. 数据更新频繁时要考虑写入策略
如果是骑手、车辆、设备轨迹等高频移动对象,位置更新会非常频繁。此时需要评估:
- 更新频率是否合理
- 是否按时间窗口保留位置
- 是否需要额外记录历史轨迹
Redis GEO 更适合存“当前点位”,历史轨迹通常另存。
5. 注意命令版本差异与使用习惯
在较新的 Redis 版本中,GEOSEARCH 是更推荐的统一检索命令。历史上有些项目会使用老的半径查询命令,但新项目建议优先围绕 GEOSEARCH 设计。
6. 不要把 GEO 结果当作最终业务结果
GEO 更适合作为候选集筛选工具。最终排序往往还要结合:
- 营业状态
- 库存
- 配送能力
- 用户偏好
- 商家权重
也就是说,GEO 解决的是“地理上接近”,不是“业务上最优”。
九、实战设计建议
1. 坐标类 key 与详情类 key 分离
推荐这样设计:
store:geo:beijing:保存地理坐标store:info:{storeId}:保存门店详细信息
这样结构清晰,更新也方便。
2. 按城市或业务域拆分 key
如果所有门店都塞进一个大 key,后续维护和查询粒度可能不够灵活。可以按城市、区域、业务线拆分。
例如:
store:geo:bj
store:geo:sh
store:geo:food
store:geo:warehouse
3. 先 GEO 粗筛,再业务层精筛
常见流程是:
- 用 GEO 找附近 50 个候选点
- 应用层根据状态和规则过滤
- 再按最终得分排序
这种设计性能和灵活性都比较好。
十、小结
GEO 是 Redis 中非常实用的地理位置能力,底层依托 Sorted Set,通过地理编码和范围检索实现“附近搜索”“距离计算”等功能。
可以重点记住以下几点:
- GEO 用来存储经纬度并做附近检索
- 底层基于 Sorted Set,不是完全独立的新存储模型
- 常用命令包括
GEOADD、GEODIST、GEOPOS、GEOSEARCH - 适合附近的人、附近门店、调度候选筛选等场景
- 注意经纬度顺序、距离含义以及能力边界
如果业务只是需要一个轻量、高效的“附近检索”能力,那么 Redis GEO 往往非常顺手;但如果业务已经走向复杂空间分析,那就要考虑更专业的地理系统来配合。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!