· 王思腾 · 系统架构 · 9 分钟阅读
外卖调度系统架构设计:分钟级履约背后的实时调度引擎
外卖履约要求在数十分钟内完成“接单—出餐—配送”。调度系统需要实时感知骑手位置、商家出餐与订单状态,在毫秒间完成亿级组合的最优匹配。本文讲清 LBS、订单流转、智能派单与运力调度是怎么设计的。

外卖是典型的 O2O 实时履约系统:用户下单后,系统要在极短时间内完成商家接单、骑手派单、路径规划,并在地图上实时回传位置。它同时考验高并发写入、地理计算和调度算法工程化能力。
一、业务全景与角色
一次外卖履约涉及四方协同:
- 用户端:下单、支付、查看进度、评价。
- 商家端:接单、备餐、叫号出餐。
- 骑手端:听单、取餐、送达,持续上报 GPS。
- 调度平台:撮合订单与骑手,做全局最优分配。
核心履约链路:
用户下单 → 商家接单/出餐 → 系统派单 → 骑手到店取餐 → 配送送达 → 结算每一步都有严格的时间承诺(ETA),任何一环超时都会影响体验和成本。
二、系统架构分层
flowchart TB
subgraph Access["接入层"]
U["用户 App"] --- M["商家 App"] --- R["骑手 App"] --- GW["API 网关"]
end
subgraph Trade["交易层"]
T1["订单"] --- T2["支付"] --- T3["营销"] --- T4["评价"]
end
subgraph Dispatch["调度层"]
D1["订单池"] --- D2["运力池"] --- D3["派单引擎"] --- D4["ETA 预估"]
end
subgraph LBS["LBS 层"]
L1["地理围栏"] --- L2["路径规划"] --- L3["实时位置"] --- L4["Geo 存储"]
end
subgraph Data["数据层"]
E1[("Redis")] --- E2["MQ"] --- E3[("时序库")] --- E4[("MySQL")] --- E5["Flink 流处理"]
end
Access --> Trade --> Dispatch --> LBS --> Data调度层是大脑,LBS 层是感知,交易层负责订单生命周期,三者通过消息与状态机解耦。
三、LBS 与实时位置
骑手每几秒上报一次经纬度,高峰期每秒数百万上报,需要专门的存储与计算:
- 地理位置存储:用 Redis GEO(GeoHash)或基于 GeoHash / H3 的分片索引,快速查询“某商家附近 N 公里的空闲骑手”。
- 位置上报链路:骑手端 → 网关 → Kafka → Flink 实时清洗/纠偏(地图匹配、去除漂移点)→ 写入在线缓存与时序库。
- 地理围栏:判断骑手是否“已到店”“已送达”,用围栏触发状态自动流转。
- 路径规划:调用地图服务算骑行 ETA,并结合历史数据做时间预估修正。
位置数据写多读少、时效性极强,冷热分离:实时位置放内存/Redis,历史轨迹落时序库或对象存储。
四、订单状态机
订单和骑手任务都用状态机驱动,典型订单状态:
stateDiagram-v2
[*] --> 待支付
待支付 --> 待接单: 支付成功
待接单 --> 备餐中: 商家接单
备餐中 --> 待取餐: 出餐
待取餐 --> 配送中: 骑手取餐
配送中 --> 已送达: 送达
已送达 --> 已完成: 确认/评价
待支付 --> 已取消: 超时/取消
已送达 --> 售后中: 申请售后
已完成 --> [*]
已取消 --> [*]骑手任务状态:待抢单/待派单 → 已接单 → 到店 → 取餐 → 配送中 → 已送达。
状态变更通过 MQ 广播,用户端、商家端、调度系统、结算系统各自订阅,保证最终一致。
五、智能派单:系统的核心
派单本质是一个实时匹配优化问题:在满足约束的前提下,把订单分给最合适的骑手,使整体准时率最高、空驶率最低。
1. 派单模式
- 抢单模式:订单发到骑手池,骑手自主抢。实现简单,但优质单被抢、偏远单无人接。
- 系统派单(调度):平台全局分配,体验和效率更优,是主流做法。
- 混合模式:系统派单为主,特定场景开放抢单。
2. 调度算法思路
派单要考虑的因素很多:骑手当前位置与负载、商家出餐时间、用户距离、顺路程度、承诺送达时间、天气与商圈拥堵。
常见工程化做法:
- 候选召回:用 Geo 索引快速圈出商家附近的可用骑手,缩小求解规模。
- 特征打分 / 成本预估:为每个“订单—骑手”组合估算成本(超时风险、骑行距离、顺路度)。
- 优化求解:
- 简单场景用贪心 + 规则(就近、就闲、顺路);
- 复杂场景用二分图匹配(KM 算法)或整数规划,批量求全局最优;
- 并单(一个骑手取多单)可建模为带容量约束的路径问题(VRP 变体)。
- 滚动调度:每隔几秒滚动重算,新订单进入、在途订单动态调整。
3. ETA 预估
准时率的关键是 ETA 准确。通常用机器学习模型(GBDT/深度网络)预测:
- 出餐时长(基于商家历史、当前订单量、菜品);
- 配送时长(基于距离、路况、天气、骑手经验)。
ETA 既用于用户展示,也作为派单成本函数的核心输入。
六、高并发与稳定性
- 削峰:午晚高峰是天然流量洪峰,下单、上报全走 MQ 异步化。
- 弹性扩容:调度服务无状态化,按 CPU/队列积压自动扩缩容。
- 降级策略:复杂算法超时则回退到简单规则派单;地图服务异常用直线距离兜底。
- 灰度与仿真:派单策略上线前用历史数据离线仿真,评估准时率和成本,再小流量灰度。
- 可观测:每一单的派单理由、ETA、轨迹全链路可回放,便于复盘和投诉处理。
七、技术选型参考
| 场景 | 选型 |
|---|---|
| 位置上报/流处理 | Kafka + Flink |
| 地理存储 | Redis GEO / GeoHash、H3 |
| 在线缓存 | Redis Cluster |
| 调度求解 | 规则引擎 + 图匹配/OR 优化器 |
| ETA 模型 | GBDT / 深度网络 + 特征平台 |
| 轨迹存储 | 时序库 / HBase / 对象存储 |
八、总结
外卖调度系统的难点不在单个技术点,而在于把实时数据、地理计算和优化算法缝合成一个稳定的在线系统:
- 用 LBS + 流计算实时感知“订单在哪、骑手在哪”;
- 用状态机 + 消息驱动订单与运力协同;
- 用“召回—预估—优化—滚动”的调度框架做全局最优派单;
- 用异步化、弹性扩容和降级兜底保证高峰稳定。
最终衡量调度系统好坏的指标很朴素:准时率、空驶率、骑手收入与用户体验——算法要服务于这些真实业务目标。
本文由 AI 辅助创作,所有内容仅供交流与参考。



