Redis GEO

Redis GEO 完全攻略

“地理位置神器” —— 附近的人、门店查询、打车路径… 10 米级精度,毫秒级响应


一、GEO 核心特点

特性说明
底层结构Sorted Set + Geohash 编码
精度约 0.1 米 ~ 10 米(取决于 Geohash 长度)
最大成员数2^32 – 1(约 42 亿)
核心命令GEOADDGEODISTGEORADIUS
性能O(log N + M),N=总成员,M=返回数量
支持单位mkmmi(英里)、ft(英尺)

GEO = Sorted Set 的高级封装


二、GEO 命令全表(共 7 个)

命令说明示例
GEOADD key longitude latitude member添加位置GEOADD cities 116.40 39.90 "北京"
GEOPOS key member [member ...]获取坐标GEOPOS cities 北京
GEODIST key m1 m2 [unit]两点距离GEODIST cities 北京 上海 km
GEOHASH key member [member ...]Geohash 编码GEOHASH cities 北京
GEORADIUS key lon lat radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT n] [ASC|DESC] [STORE key] [STOREDIST key]圆形范围查询GEORADIUS cities 116.40 39.90 100 km
GEORADIUSBYMEMBER key member radius unit ...以成员为中心GEORADIUSBYMEMBER cities 北京 200 km
GEOSEARCH key [FROMMEMBER m] [FROMLONLAT lon lat] [BYRADIUS r unit] [BYBOX w h unit] [ASC|DESC] [COUNT n] [WITHCOORD] [WITHDIST] [WITHHASH] [STORE key] [STOREDIST key]Redis 6.2+ 高级查询GEOSEARCH cities FROMLONLAT 116.40 39.90 BYRADIUS 100 km

三、核心实战场景


1. 附近的人(社交 App)

# 添加用户位置
GEOADD users:online 116.40 39.90 "user:1001"
GEOADD users:online 116.41 39.91 "user:1002"

# 查询 5km 内的人
GEORADIUS users:online 116.40 39.90 5 km WITHDIST WITHCOORD COUNT 10 ASC

返回示例

1) 1) "user:1001"
   2) "0.0000"           # 距离(km)
   3) 1) "116.400000000000006"
      2) "39.900000000000006"
2) 1) "user:1002"
   2) "1.4142"
   3) ...

2. 附近门店查询

# 添加门店
GEOADD stores 116.40 39.90 "朝阳店"
GEOADD stores 116.38 39.88 "海淀店"

# 查询最近 3 家门店
GEORADIUSBYMEMBER stores 朝阳店 10 km WITHDIST COUNT 3 ASC

3. 打车路径优化(司机匹配)

# 司机位置
GEOADD drivers:online 116.39 39.89 "driver:001"

# 乘客下单
GEORADIUS drivers:online 116.40 39.90 3 km COUNT 1 ASC
# 返回最近司机

4. 矩形区域查询(Redis 6.2+)

# 查询北京五环内(矩形)
GEOSEARCH cities \
  FROMLONLAT 116.10 39.70 \
  BYBOX 60 40 km \
  WITHCOORD WITHDIST

四、GEO vs 数据库 对比

对比项Redis GEOMySQL GEOMETRY
查询速度毫秒级秒级
内存占用极低
实时更新支持支持
复杂查询圆形/矩形支持任意
推荐场景高并发、简单范围复杂 GIS

结论:附近的人/门店 → GEO,复杂地图 → PostGIS


五、Geohash 编码原理

北京: 116.40, 39.90 → Geohash: wx4g0s
上海: 121.47, 31.23 → Geohash: wtw3sj

精度对照表

Geohash 长度误差应用
5±2.5 km城市级
6±0.6 km区域级
7±0.15 km街道级
8±40 m建筑级
9±10 m推荐

Redis 内部使用 52 位 Geohash,精度 ≈ 0.6 米


六、性能与内存优化建议

建议说明
控制成员数 < 100万避免 ZSet 退化
用 ID 替代长名称user:1001 而非 "张三"
设置 TTLEXPIRE users:online 300
分片存储users:online:beijingusers:online:shanghai
COUNT 限制返回COUNT 50
# 分片 + TTL
GEOADD users:online:beijing 116.40 39.90 "u1"
EXPIRE users:online:beijing 300

七、大 key 排查与拆分

# 排查大 GEO
redis-cli --bigkeys
# Biggest zset found "users:online" with 5000000 members

拆分方案

# 按城市分片
users:online:beijing
users:online:shanghai
users:online:guangzhou

八、一键速查表

# 添加位置
GEOADD loc 116.40 39.90 "北京" 121.47 31.23 "上海"

# 距离
GEODIST loc 北京 上海 km

# 附近查询
GEORADIUS loc 116.40 39.90 100 km WITHDIST WITHCOORD COUNT 10

# 以成员为中心
GEORADIUSBYMEMBER loc 北京 200 km

# 高级查询(Redis 6.2+)
GEOSEARCH loc FROMLONLAT 116.40 39.90 BYRADIUS 50 km COUNT 20

九、客户端代码示例

Python (redis-py)

import redis
r = redis.Redis()

# 添加用户位置
r.geoadd('users:online', (116.40, 39.90, 'user:1001'))
r.geoadd('users:online', (116.41, 39.91, 'user:1002'))

# 查询附近 5km 内用户
nearby = r.georadius('users:online', 116.40, 39.90, 5, unit='km', withdist=True, withcoord=True, count=10, sort='ASC')
for user, dist, coord in nearby:
    print(f"用户: {user.decode()}, 距离: {dist}m, 坐标: {coord}")

Go (go-redis)

ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})

rdb.GeoAdd(ctx, "cities", &redis.GeoLocation{Longitude: 116.40, Latitude: 39.90, Name: "北京"})
dist, _ := rdb.GeoDist(ctx, "cities", "北京", "上海", "km").Result()
fmt.Printf("距离: %.2f km\n", dist)

十、常见问题与解决方案

问题原因解决方案
精度不够Geohash 误差WITHCOORD 后端二次计算
查询慢成员太多分片 + COUNT
内存暴涨无限添加TTL + 分片
坐标错误经纬度反了经度在前,纬度在后

十一、GEO 在高并发中的妙用

1. 实时位置更新 + 附近推送

-- Lua 脚本:更新位置 + 查询附近
EVAL "
  redis.call('geoadd', KEYS[1], ARGV[1], ARGV[2], ARGV[3])
  return redis.call('georadius', KEYS[1], ARGV[1], ARGV[2], 1, 'km', 'WITHCOORD', 'COUNT', 10)
" 1 users:online 116.40 39.90 user:1001

2. LBS 反作弊(位置跳跃检测)

# 记录上次位置
GEOPOS users:last user:1001
# 计算与当前距离 > 100km/h → 异常

完成!你已精通 Redis GEO!

# 一行命令体验 GEO 全功能
redis-cli <<EOF
GEOADD loc 116.40 39.90 "北京" 121.47 31.23 "上海"
GEODIST loc 北京 上海 km
GEORADIUS loc 116.40 39.90 1000 km WITHDIST WITHCOORD COUNT 2
GEOHASH loc 北京
EOF

下一步推荐

  1. Redis Stream + GEO 实现实时轨迹
  2. GEO + Lua 实现高性能附近推送
  3. 亿级用户 LBS 架构(分片 + 缓存)

需要我送你

  • “附近的人完整系统(GEO + 在线状态 + 推送)”
  • “门店推荐引擎(GEO + 评分排序)”
  • “实时轨迹回放(GEO + Stream)”

回复:附近的人 | 门店推荐 | 轨迹回放 即可!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部