首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从0到1搭建外卖跑腿配送系统全流程解析

从0到1搭建外卖跑腿配送系统全流程解析

原创
作者头像
万岳教育Lili
发布2026-07-02 11:14:14
发布2026-07-02 11:14:14
1140
举报

外卖跑腿配送系统本质上是一个“多角色 + 实时调度 + 地理位置驱动”的同城即时履约系统,核心围绕四个端:用户端、商家端、骑手端、管理后台。

下面从业务流程到技术架构,再到核心代码实现,带你完整拆解一套可落地的系统设计。

外卖跑腿配送系统
外卖跑腿配送系统

一、系统整体架构设计

一个标准外卖跑腿系统通常采用分层+微服务/模块化架构:

1. 业务端结构

  • 用户端:下单、支付、追踪订单
  • 商家端:接单、出餐、订单管理
  • 骑手端:抢单/派单、配送、签收
  • 管理后台:订单调度、风控、数据分析

2. 技术架构

  • 前端:Vue / React / 小程序 / App
  • 后端:Java Spring Boot / Node.js / Go
  • 数据库:MySQL + Redis
  • 地图服务:高德 / Google Maps
  • 消息系统:WebSocket / MQTT
  • 定位系统:GPS + LBS

二、核心业务流程

外卖跑腿系统的主链路:

  1. 用户下单
  2. 商家接单
  3. 系统派单(或抢单)
  4. 骑手接单
  5. 骑手取餐
  6. 骑手配送
  7. 完成订单
  8. 结算与评价

关键点在第3步:派单逻辑


三、核心模块拆解

1. 订单模块

订单是整个系统的核心数据结构。

示例:订单表设计(简化)

代码语言:javascript
复制
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 示例

代码语言:javascript
复制
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实现骑手定位

代码语言:javascript
复制
// 骑手上线(存位置)
await redis.geoadd(
    "riders_location",
    longitude,
    latitude,
    riderId
);

查询附近骑手

代码语言:javascript
复制
const riders = await redis.georadius(
    "riders_location",
    orderLng,
    orderLat,
    3,          // 3公里范围
    "km",
    "WITHDIST",
    "COUNT",
    5
);

派单逻辑(核心代码)

代码语言:javascript
复制
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)

骑手必须“秒级收到订单”

代码语言:javascript
复制
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. 骑手接单逻辑

代码语言:javascript
复制
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. 定位更新(骑手端)

骑手位置需要持续上报:

代码语言:javascript
复制
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);

后端存储更新:

代码语言:javascript
复制
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)
代码语言:javascript
复制
const lock = await redis.set("order_lock_" + orderId, riderId, "NX", "EX", 10);
if (!lock) {
    return "订单已被抢";
}

五、系统升级方向(进阶)

如果要做商业级系统,必须加:

  • 智能派单(AI算法:距离+负载+评分)
  • 动态调度(订单合并配送)
  • 路径规划优化(A* / Dijkstra)
  • 风控系统(异常骑手检测)
  • 大数据分析(热区预测)

外卖跑腿配送系统
外卖跑腿配送系统

六、总结

外卖跑腿配送系统的核心不是“下单”,而是:

实时调度 + 地理位置 + 多角色协同

真正的技术难点集中在三点:

  • 派单算法
  • 实时通信
  • 高并发处理

如果这三块做好,系统才算真正可商用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、系统整体架构设计
    • 1. 业务端结构
    • 2. 技术架构
  • 二、核心业务流程
  • 三、核心模块拆解
    • 1. 订单模块
      • 示例:订单表设计(简化)
    • 2. 下单接口(后端示例)
      • Node.js 示例
    • 3. 派单核心逻辑(重点)
      • 思路:
      • Redis GEO实现骑手定位
      • 查询附近骑手
      • 派单逻辑(核心代码)
    • 4. 实时订单推送(WebSocket)
    • 5. 骑手接单逻辑
    • 6. 定位更新(骑手端)
    • 后端存储更新:
  • 四、关键技术难点
    • 1. 高并发订单处理
    • 2. 实时性
    • 3. 距离计算
    • 4. 防止抢单冲突
  • 五、系统升级方向(进阶)
  • 六、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档