很多人做开源外卖系统时,一开始只考虑“自营骑手”。
但只要订单量一上来,就会发现一个现实问题:
- 高峰期运力不够
- 低峰期人力成本过高
- 跨区域订单履约困难
这时候,单一运力模式必然成为瓶颈。
真正成熟的开源外卖系统,必须支持:
自营骑手 + 众包骑手 + 第三方运力并存
今天我们从架构设计 + 数据结构 + 核心代码实现三个层面,拆解多运力模型如何落地。
一、多运力模型的核心设计思路
多运力并存,本质是三件事:
- 订单如何选择运力类型
- 不同运力如何分账
- 调度如何统一抽象
我们先定义一个核心原则:
订单只认“运力策略”,不直接绑定某个骑手类型。
二、数据库结构设计
1. 运力类型表
CREATE TABLE delivery_provider (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
provider_name VARCHAR(50),
provider_type VARCHAR(20), -- SELF / CROWD / THIRD_PARTY
status TINYINT DEFAULT 1,
create_time DATETIME
);
说明:
- SELF:自营骑手
- CROWD:众包骑手
- THIRD_PARTY:第三方运力接口
2. 骑手表(统一抽象)
CREATE TABLE rider (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
phone VARCHAR(20),
provider_id BIGINT,
status VARCHAR(20), -- ONLINE / OFFLINE / BUSY
latitude DECIMAL(10,6),
longitude DECIMAL(10,6),
FOREIGN KEY (provider_id) REFERENCES delivery_provider(id)
);
关键点:
不管自营还是众包,统一用 rider 表管理,只通过 provider_id 区分来源。
3. 订单表增加运力字段
ALTER TABLE orders
ADD COLUMN provider_id BIGINT,
ADD COLUMN dispatch_status VARCHAR(20);
三、运力选择策略设计
多运力的核心在于“派单策略”。
常见策略:
- 优先自营(成本可控)
- 自营无可用骑手 → 自动切换众包
- 众包仍不足 → 调用第三方接口
四、核心调度逻辑实现(Java示例)
1. 运力策略接口
public interface DispatchStrategy {
Rider dispatch(Order order);
}
2. 自营策略实现
public class SelfDispatchStrategy implements DispatchStrategy {
@Override
public Rider dispatch(Order order) {
List<Rider> riders = riderRepository.findAvailableRiders("SELF");
return riders.stream()
.min(Comparator.comparing(r -> distance(r, order)))
.orElse(null);
}
private double distance(Rider rider, Order order) {
return GeoUtil.calculateDistance(
rider.getLatitude(),
rider.getLongitude(),
order.getLatitude(),
order.getLongitude()
);
}
}
3. 众包策略实现
public class CrowdDispatchStrategy implements DispatchStrategy {
@Override
public Rider dispatch(Order order) {
List<Rider> riders = riderRepository.findAvailableRiders("CROWD");
return riders.stream()
.min(Comparator.comparing(r -> distance(r, order)))
.orElse(null);
}
private double distance(Rider rider, Order order) {
return GeoUtil.calculateDistance(
rider.getLatitude(),
rider.getLongitude(),
order.getLatitude(),
order.getLongitude()
);
}
}
4. 运力调度中心(核心控制)
public class DispatchCenter {
private DispatchStrategy selfStrategy;
private DispatchStrategy crowdStrategy;
public Rider dispatch(Order order) {
Rider rider = selfStrategy.dispatch(order);
if (rider != null) {
order.setProviderId(1L); // SELF
return rider;
}
rider = crowdStrategy.dispatch(order);
if (rider != null) {
order.setProviderId(2L); // CROWD
return rider;
}
// 调用第三方接口
return thirdPartyDispatch(order);
}
private Rider thirdPartyDispatch(Order order) {
// 调用第三方API
ThirdPartyResponse response = thirdPartyApi.createOrder(order);
return convert(response);
}
}
核心思想:
策略模式 + 运力优先级控制
五、分账逻辑差异处理
不同运力,成本不同。
示例:
public BigDecimal calculateRiderIncome(Order order) {
if (order.getProviderType().equals("SELF")) {
return order.getDeliveryFee().multiply(new BigDecimal("0.8"));
}
if (order.getProviderType().equals("CROWD")) {
return order.getDeliveryFee().multiply(new BigDecimal("0.9"));
}
if (order.getProviderType().equals("THIRD_PARTY")) {
return order.getDeliveryFee().subtract(order.getThirdPartyCost());
}
return BigDecimal.ZERO;
}
重点:
- 自营:利润高
- 众包:抽成低
- 第三方:按接口成本结算
六、高并发优化建议
多运力场景下,必须避免:
- 重复派单
- 同时抢单冲突
可以使用 Redis 分布式锁:
String lockKey = "dispatch_lock:" + order.getId();
Boolean success = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!success) {
throw new RuntimeException("正在派单中");
}
七、为什么多运力模型很重要?
如果只有自营骑手:
- 扩张慢
- 高峰易崩
- 成本难控制
如果只有众包:
- 服务质量不稳定
- 抽成空间低
多运力并存的意义是:
平峰自营,高峰众包,极端情况第三方托底。
这才是可扩展架构。

结语
开源外卖系统如果只停留在“下单+接单”,那只是基础版本。
真正成熟的平台,必须具备:
- 多运力抽象模型
- 可扩展调度策略
- 分账差异化逻辑
- 高并发防冲突机制
做系统,不是堆功能,而是设计结构。
多运力并存模型,是外卖系统从“小工具”走向“平台级架构”的关键一步。
