在高并发外卖系统中如何利用Redis GEO计算骑手与商家距离

风枫酱_9496

风枫酱_9496

2026-10-14

869人浏览

原创

用geosearch替代georadius,配合统一wgs84坐标系、批量预热商家位置、显式指定单位(如m)、限制count及加asc排序,才能稳定支撑骑手高频上报与并发查距。

在高并发外卖系统中如何利用redis geo计算骑手与商家距离

直接结论:用 GEOSEARCH 替代 GEORADIUS,配合统一坐标系 + 批量预热 + 单位显式指定,才能扛住骑手位置高频刷新与并发查距的双重压力。

为什么不能只用 GEORADIUS 查骑手距离

很多团队一开始写成 GEORADIUS shop:geo $lng $lat 500 m COUNT 1 去找最近骑手,结果在 QPS 上千时延迟突增、超时频发。根本原因有三个:

  • GEORADIUS 每次都以经纬度为中心做球面扫描,Redis 需实时解码所有 GeoHash 并逐个比对,计算开销随半径内点数线性增长
  • 骑手位置每 3–5 秒上报一次,若用 GEORADIUS 查“离某商家最近的骑手”,本质是遍历全量骑手集合,没利用 zset 的有序性优势
  • 单位不显式指定(比如漏写 m)会导致 Redis 默认用 m,但业务逻辑按 km 解析,距离误判率陡升

GEOSEARCH 怎么查才真正高效

核心思路是把“查骑手”变成“查商家”——让骑手作为查询主体,反向检索其覆盖范围内的可接单商家。但在调度场景中,我们仍需知道“某个商家附近有哪些骑手”,此时应改用 FROMMEMBER 模式,让商家作为锚点:

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
  • 先确保商家已写入:geoAdd('shop:active', $lng, $lat, $shopId),注意经度在前、纬度在后
  • 骑手位置单独存入另一 key:geoAdd('rider:live', $lng, $lat, $riderId),保持数据隔离
  • 查商家 $shopId 周边 1.5km 内骑手:GEOSEARCH rider:live FROMMEMBER $shopId BYRADIUS 1500 m ASC COUNT 3 WITHDIST
  • 必须加 ASC,否则默认无序;COUNT 3 要严格限制,避免返回几十个骑手再由 PHP 二次筛选

坐标系不一致是静默故障最大来源

高德地图 SDK 返回的是 GCJ-02 坐标,而 Redis GEO 内部用 WGS84 球面模型计算 haversine 距离。两者混用会导致 100–500 米偏差,调度系统会频繁选错骑手。

  • 前后端必须约定统一坐标系:推荐全部转为 WGS84(可用 gcoord 库或高德 API 的 convert 接口)
  • 不要在 Redis 里存“转换中”的坐标,例如前端传 GCJ-02,后端一边转一边写 —— 转换失败时写入的就是脏数据
  • 上线前用固定坐标对打:取北京望京某商家(WGS84: 116.48105,39.996794),查它周围 500m 骑手,再用高德 JSAPI 同样半径画圆,看结果是否重合

真实压测下容易被忽略的三个细节

即便命令写对、坐标对齐,QPS 过万后仍可能抖动。问题往往出在这些非代码层:

  • Redis 实例未开启 io-threads(Tair 或 GaussDB(for Redis) 必须显式配置,开源 Redis 6.0+ 需编译时启用)
  • rider:live key 没设置过期时间,骑手下线后位置残留,GEOSEARCH 仍会扫到“幽灵骑手”
  • PHP 中调用 $redis->geoSearch() 时未捕获异常,当 Redis 返回空数组或 NULL 时,业务层直接报 foreach() on null,掩盖了底层 GEO 查询失败

最麻烦的是:这些细节在本地单机测试完全暴露不出来,只有压测到 8k QPS 以上、骑手模拟器并发上报时,才会集中爆发。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

redis

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4429

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3975

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

7292

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

643

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

756

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

7082

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1160

6

redis的8种数据类型有哪些
redis的8种数据类型有哪些

redis 提供 8 种数据类型:字符串(文本、数字、二进制)、哈希(键值对)、列表(有序集合)、集合(无序唯一元素)、有序集合(按分数排序)、地理空间(地理位置)、hyperloglog(估计大数据基数)和位图(位序列存储)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1076

6

redis主要作用有哪些
redis主要作用有哪些

redis 的主要作用包括:1. 缓存数据,提高访问速度;2. 充当消息队列,实现消息传递;3. 存储各种数据类型,如字符串、散列和集合;4. 管理会话信息,确保可靠性和可用性;5. 限制请求速率,防止服务器超载等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

6218

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习