外卖跑腿配送系统本质上是一个“多角色 + 实时调度 + 地理位置驱动”的同城即时履约系统,核心围绕四个端:用户端、商家端、骑手端、管理后台。
下面从业务流程到技术架构,再到核心代码实现,带你完整拆解一套可落地的系统设计。
一、系统整体架构设计
一个标准外卖跑腿系统通常采用分层+微服务/模块化架构:
1. 业务端结构
- 用户端:下单、支付、追踪订单
- 商家端:接单、出餐、订单管理
- 骑手端:抢单/派单、配送、签收
- 管理后台:订单调度、风控、数据分析
2. 技术架构
- 前端:Vue / React / 小程序 / App
- 后端:Java Spring Boot / Node.js / Go
- 数据库:MySQL + Redis
- 地图服务:高德 / Google Maps
- 消息系统:WebSocket / MQTT
- 定位系统:GPS + LBS
二、核心业务流程
外卖跑腿系统的主链路:
- 用户下单
- 商家接单
- 系统派单(或抢单)
- 骑手接单
- 骑手取餐
- 骑手配送
- 完成订单
- 结算与评价
关键点在第3步:派单逻辑
三、核心模块拆解
1. 订单模块
订单是整个系统的核心数据结构。
示例:订单表设计(简化)
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
merchant_id BIGINT,
rider_id BIGINT,
status VARCHAR(20),
total_amount DECIMAL(10,2),
create_time DATETIME,
update_time DATETIME
);
2. 下单接口(后端示例)
Node.js 示例
app.post("/order/create", async (req, res) => {
const {
userId, merchantId, items } = req.body;
// 1. 计算金额
const total = items.reduce((sum, item) => {
return sum + item.price * item.count;
}, 0);
// 2. 创建订单
const order = await db.orders.create({
user_id: userId,
merchant_id: merchantId,
total_amount: total,
status: "PENDING"
});
// 3. 写入Redis用于派单
await redis.lpush("order_queue", order.id);
res.json({
success: true,
orderId: order.id
});
});
3. 派单核心逻辑(重点)
外卖系统“智能化”的核心就在这里:如何匹配最近骑手
思路:
- 获取订单位置
- 查找附近骑手(LBS)
- 计算距离
- 分配最近骑手
Redis GEO实现骑手定位
// 骑手上线(存位置)
await redis.geoadd(
"riders_location",
longitude,
latitude,
riderId
);
查询附近骑手
const riders = await redis.georadius(
"riders_location",
orderLng,
orderLat,
3, // 3公里范围
"km",
"WITHDIST",
"COUNT",
5
);
派单逻辑(核心代码)
async function dispatchOrder(orderId, orderLng, orderLat) {
const riders = await redis.georadius(
"riders_location",
orderLng,
orderLat,
5,
"km",
"WITHDIST"
);
if (!riders.length) {
throw new Error("暂无可用骑手");
}
// 按距离排序
riders.sort((a, b) => a[1] - b[1]);
const selectedRider = riders[0][0];
// 更新订单
await db.orders.update({
where: {
id: orderId },
data: {
rider_id: selectedRider,
status: "DISPATCHED"
}
});
// 通知骑手(WebSocket/MQTT)
notifyRider(selectedRider, orderId);
return selectedRider;
}
4. 实时订单推送(WebSocket)
骑手必须“秒级收到订单”
const WebSocket = require("ws");
const wss = new WebSocket.Server({
port: 8080 });
wss.on("connection", (ws) => {
ws.on("message", (msg) => {
const data = JSON.parse(msg);
if (data.type === "rider_login") {
ws.riderId = data.riderId;
}
});
});
// 推送订单
function notifyRider(riderId, orderId) {
wss.clients.forEach(client => {
if (client.riderId === riderId) {
client.send(JSON.stringify({
type: "NEW_ORDER",
orderId
}));
}
});
}
5. 骑手接单逻辑
app.post("/rider/accept", async (req, res) => {
const {
riderId, orderId } = req.body;
const order = await db.orders.findById(orderId);
if (order.status !== "DISPATCHED") {
return res.json({
success: false, msg: "订单已被接单" });
}
await db.orders.update({
where: {
id: orderId },
data: {
status: "ACCEPTED",
rider_id: riderId
}
});
res.json({
success: true });
});
6. 定位更新(骑手端)
骑手位置需要持续上报:
setInterval(() => {
navigator.geolocation.getCurrentPosition(async (pos) => {
await fetch("/rider/location/update", {
method: "POST",
body: JSON.stringify({
riderId,
lng: pos.coords.longitude,
lat: pos.coords.latitude
})
});
});
}, 5000);
后端存储更新:
app.post("/rider/location/update", async (req, res) => {
const {
riderId, lng, lat } = req.body;
await redis.geoadd("riders_location", lng, lat, riderId);
res.json({
success: true });
});
四、关键技术难点
1. 高并发订单处理
- Redis队列削峰
- MQ异步派单
- 分库分表
2. 实时性
- WebSocket替代HTTP轮询
- MQTT优化移动端连接
3. 距离计算
- Redis GEO(推荐)
- Haversine公式(备用)
4. 防止抢单冲突
- 分布式锁(Redis SETNX)
const lock = await redis.set("order_lock_" + orderId, riderId, "NX", "EX", 10);
if (!lock) {
return "订单已被抢";
}
五、系统升级方向(进阶)
如果要做商业级系统,必须加:
- 智能派单(AI算法:距离+负载+评分)
- 动态调度(订单合并配送)
- 路径规划优化(A* / Dijkstra)
- 风控系统(异常骑手检测)
- 大数据分析(热区预测)

六、总结
外卖跑腿配送系统的核心不是“下单”,而是:
实时调度 + 地理位置 + 多角色协同
真正的技术难点集中在三点:
- 派单算法
- 实时通信
- 高并发处理
如果这三块做好,系统才算真正可商用。