代驾系统智能派单拆解:Redis GEO + 距离评分的派单链路怎么设计

0 阅读3分钟

派单是代驾系统的调度核心

用户下单后,系统要在几秒内从成百上千个司机里选出“最合适的那几个”推送订单。派单慢,用户等待流失;派单不准,司机不愿意接。本文拆解一套开源代驾系统的智能派单链路。

源码地址: gitee.com/zhoujian666…

派单要解决的三个问题

  1. 找得到:怎么快速知道用户附近有哪些在线司机
  2. 排得准:附近司机里,先推给谁
  3. 转得动:第一个没接怎么办,怎么自动流转

一、附近司机检索:为什么用 Redis GEO

如果每次都查数据库算距离,高并发下数据库扛不住,且实时性差。系统让所有在线司机的实时位置写入 Redis:

  • 司机端通过 Netty WebSocket 长连接每隔几秒上报 GPS 坐标
  • 服务端用 Redis 的 GEO 数据结构(GEOADD)存“司机 ID → 经纬度”

派单时用 GEOSEARCH(或 GEORADIUS)按“用户上车点 + 半径”一次性取出附近在线司机,操作是内存级的,延迟在毫秒级。

同时用 Redis 记录司机在线状态,离线或心跳超时的司机不会进候选集。

二、排序:不是只看距离

取出附近司机后,要综合多个维度打分排序:

  • 距离:离上车点越近优先级越高(接驾时间短)
  • 司机评分:历史服务星级、好评率
  • 服务分/完单率:取消率低、完单稳定的优先
  • 司机当前状态:是否有未完成订单、是否设置忙碌

实践中常用“加权打分”或“先硬过滤再排序”:先用硬性条件(在线、空闲、证件有效)过滤,再按距离和评分加权排序。

三、推送与流转

排序后的候选司机不是同时推送,而是分轮:

  1. 取 Top N 司机,通过 Netty 通道定向推送订单(含预估里程与收入)
  2. 设置接单超时窗口(如 15 - 30 秒)
  3. 有人抢单:订单锁定,通知其他司机该单已结束
  4. 无人接单:扩大搜索半径或降低条件,进入下一轮推送
  5. 多轮失败:订单进入“调度失败”状态,后台可介入改派或通知用户

抢单并发控制

多个司机同时点“抢单”时,必须保证只成功一个。系统用分布式锁(Redis)或数据库乐观锁:以订单 ID 为锁键,第一个抢到的司机拿到锁、更新订单状态,其余抢单请求直接返回“已被接”。

派单和计价、推送的联动

  • 下单时先调用高德路径规划算预估里程,配合计价引擎给出预估价
  • 推送内容带上预估价,司机决策更清晰
  • 派单结果、状态变更通过领域事件触发 Netty 推送和 RabbitMQ 异步通知

性能与稳定性细节

  • 位置上报有节流:坐标变化太小或时间间隔太短不上报,减轻写入压力
  • Redis 操作设超时与降级:缓存异常时可降级为数据库粗筛
  • 推送失败可补偿:关键派单消息配合 MQ 做可靠投递

项目其他模块

除智能派单外,系统还包含:订单状态机、Netty WebSocket 实时推送、计价引擎、微信/支付宝支付、分润对账、管理后台。后端 + 管理后台已开源(Java 17 + Spring Boot 2.7 + Vue),可直接部署。

源码:gitee.com/zhoujian666…

欢迎评论区交流派单与 LBS 相关设计,觉得有用欢迎 Star。