news 2026/7/19 4:51:32

Redis Geo实现地理位置检索

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis Geo实现地理位置检索

做业务开发时,我们经常遇到这类需求:

✅ 同城筛选附近门店、外卖骑手匹配
✅ 社交APP附近的人、同城动态
✅ 网约车就近派单、地理位置打卡

面对这些地理位置检索场景,无需引入笨重的专业GIS引擎,Redis自带的GEO地理空间索引是一个轻量、高性能的方案。

Redis Geo
Redis Geo 没有创造新结构,完全基于有序集合 Sorted Set(ZSet)实现,底层核心组合:GeoHash 编码 + Sorted Set 索引。
简单来说就是:把二维的经纬度坐标,通过算法压缩成一维整数分值,利用ZSet天然的排序、范围检索能力,实现高效的地理位置查询。

Key:地理集合名(如 stores:location 门店位置集合)
Member:位置唯一标识(店铺ID、用户ID、设备ID)
Score:经纬度编码后的52位GeoHash整数(排序、检索的核心)
GeoHash 编码
GeoHash的核心价值:将二维经纬度,转化为可排序、可比对的一维字符串。
相近的地理位置,会拥有高度相似的编码前缀,这也是“附近查询”能够高效实现的根本原因。

GeoHash编码流程:

区间划分:针对地球经度范围[-180, 180]与纬度范围[-90, 90],开展持续的二分操作
二进制编码:在每次二分过程中,依据目标点所处区间(左区间记为0,右区间记为1)生成对应的二进制位,且经度与纬度的编码过程交替进行
Base32编码:将生成的二进制数据流,按每5位为一组转换为Base32字符
核心命令
命令 作用
GEOADD key longitude latitude member […] 添加一个或多个地理位置
GEOPOS key member […] 获取指定成员的经纬度信息
GEODIST key member1 member2 [unit] 计算两个成员之间的直线距离
GEOHASH key member […] 获取成员对应的GeoHash编码,主要用于调试场景
GEOSEARCH key FROMMEMBER member BYRADIUS radius unit […] 以已存储的成员为中心,检索指定圆形区域内的位置
GEOSEARCH key FROMLONLAT lng lat BYRADIUS radius unit […] 以给定的经纬度为中心,检索指定圆形区域内的位置
GEOSEARCH key FROMLONLAT lng lat BYBOX width height unit […] 检索指定矩形区域内的位置
GEORADIUS key FROMLONLAT lng lat BYBOX width height unit […] 检索指定矩形区域内的位置,该命令已废弃
实战演练:实现「附近店铺」功能
将店铺位置录入Redis
将店铺的经纬度信息添加至Redis数据库

GEOADD storeId:location 116.48 39.95 store:1001
GEOADD storeId:location 116.50 39.96 store:1002
GEOADD storeId:location 116.30 39.90 store:1003
💡 该操作支持批量添加,可一次性录入多个位置信息,能有效提升操作性能。

检索附近的店铺
当用户A位于(116.48, 39.95)时,若需查询5公里范围内的店铺,可执行如下操作:

GEOSEARCH storeId:location
FROMLONLAT 116.48 39.95 \ # 以指定经纬度为中心
BYRADIUS 5 km \ # 搜索半径5公里
WITHDIST \ # 返回距离中心点的距离
WITHCOORD \ # 返回目标的经纬度
COUNT 20 ASC # 最多20条,由近及远排序

Redis 6.2 以下旧版本,可使用以下命令

GEORADIUS storeId:location 116.48 39.95 5 km WITHCOORD
Java代码

@Service
public class LocationService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String GEO_KEY = “storeId:location”;

public void updateLocation(Long storeId, double lng, double lat) { // 先删旧位置,再添加新位置 redisTemplate.opsForGeo().remove(GEO_KEY, storeId.toString()); redisTemplate.opsForGeo().add(GEO_KEY, new Point(lng, lat), storeId.toString()); } public GeoResults<RedisGeoCommands.GeoLocation<String>> findNearby(double lng, double lat, double radius) { Circle circle = new Circle(new Point(lng, lat), new Distance(radius, Metrics.KILOMETERS)); return redisTemplate.opsForGeo().radius(GEO_KEY, circle, RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs() .includeDistance() .includeCoordinates() .sortAscending() .limit(20));
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 4:50:59

ADS1292芯片在医疗电子中的SPI接口与数据采集实现

1. ADS1292芯片方案概述ADS1292是TI推出的低功耗、双通道24位Δ-Σ模数转换器&#xff0c;专用于生物电势信号采集。这颗芯片在医疗电子领域应用广泛&#xff0c;特别是便携式心电图(ECG)和脑电图(EEG)设备。其核心优势在于集成了可编程增益放大器(PGA)、内部基准电压和右腿驱动…

作者头像 李华
网站建设 2026/7/19 4:50:43

Golua标准库详解:Go中安全嵌入Lua脚本的实践指南

1. Golua标准库&#xff1a;连接Go与Lua的桥梁如果你正在用Go语言开发&#xff0c;但项目中需要嵌入一个轻量、灵活、易于热更新的脚本引擎&#xff0c;那么Lua几乎是你的不二之选。而Golua&#xff0c;就是连接Go世界与Lua世界的官方桥梁。它基于Lua的C API&#xff0c;通过cg…

作者头像 李华
网站建设 2026/7/19 4:50:31

Python常用模块详解与实战应用指南

1. Python常用模块概述作为一门通用编程语言&#xff0c;Python的强大之处很大程度上来自于其丰富的标准库和第三方模块。这些模块就像是Python生态中的"瑞士军刀"&#xff0c;让开发者能够快速实现各种功能而无需重复造轮子。对于初学者来说&#xff0c;掌握常用模块…

作者头像 李华
网站建设 2026/7/19 4:48:29

C++高性能批量无锁队列实现:原理、设计与工程实践

1. 项目概述&#xff1a;为什么我们需要批量操作的无锁队列&#xff1f;在并发编程的世界里&#xff0c;队列是一个再基础不过的数据结构。无论是生产者-消费者模型&#xff0c;还是任务分发、日志缓冲&#xff0c;队列都扮演着核心角色。传统的队列实现&#xff0c;比如用std:…

作者头像 李华
网站建设 2026/7/19 4:48:21

Java设计模式实战:核心价值与典型应用解析

1. 设计模式在Java开发中的核心价值设计模式是面向对象编程中经过验证的最佳实践方案&#xff0c;它们不是具体的代码实现&#xff0c;而是针对特定问题的通用解决方案模板。在Java开发中&#xff0c;设计模式的价值主要体现在三个方面&#xff1a;首先&#xff0c;设计模式提供…

作者头像 李华