物流主数据服务迁移与架构改造方案
1. 项目背景
随着公司物流业务规模持续增长,系统架构逐渐演进为多微服务体系。当前系统包含订单中心、物流管理系统、结算系统、移动终端系统等多个业务服务,各服务在运行过程中均需要访问物流主数据,例如客户、承运商、车辆、司机、线路、网点等信息。
目前这些主数据主要由 wpglb-lms-service
服务提供,但随着系统的发展,该服务逐渐暴露出一系列架构问题。
主要问题包括:
- LMS缺乏未来扩展性,并且定义不准确。
- 主数据访问方式不统一:部分服务直连 DB,部分通过
LMS,部分硬编码字典,缺乏统一标准。 - 主数据治理能力不足:缺乏统一的数据标准、质量监控和生命周期管理。
- 服务扩展和维护成本不断增加:LMS
服务成为瓶颈,且任何主数据表结构变更需全链路回归。
为解决上述问题,需要将现有主数据能力进行重构,建立统一的
物流基础数据中心服务(wpglb-dms-basic),实现主数据服务化、领域边界清晰化以及系统解耦。
2. 现状分析
2.1 当前系统服务结构
分类 服务/模块 职责描述 当前主数据依赖方式
公共服务 wpglb-tool 公共组件库 -
公共服务 wpglb-service-api Feign接口及DTO定义 包含LMS的Feign Client
公共服务 wpgl-commons 公共工具包 -
基础服务 wpglb-gateway API网关 -
基础服务 wpglb-system 系统管理服务 直连DB(用户/组织)
基础服务 wpglb-auth 认证鉴权服务 直连DB(权限)
物流主数据 wpglb-lms-service 物流主数据服务 核心依赖
业务服务 wpglb-dms-orders 业务管理系统 SQL JOIN LMS表
业务服务 wpglb-dms-pda PDA终端服务 SQL JOIN LMS表
业务服务 wpglb-dms-driver-service 司机APP服务端 SQL JOIN LMS表
业务服务 wpglb-dms-task 任务中心 调用LMS Feign
结算系统 wpglb-dbms 结算服务 SQL JOIN LMS表
结算系统 wpglb-dbms-task 结算定时任务 调用LMS Feign
2.2 当前数据访问模式痛点
目前业务服务大量采用 SQL 连表查询方式获取主数据。
示例(反模式):
-- 订单查询时直接关联主数据表
SELECT o.order_no, o.status, c.customer_name, v.plate_number
FROM order_info o
LEFT JOIN customer c ON o.customer_id = c.id
LEFT JOIN vehicle v ON o.vehicle_id = v.id
WHERE o.create_time > '2026-01-01';
这种模式造成的问题:
- 边界被破坏:业务逻辑与主数据强耦合,违反 DDD 原则。
- SQL复杂度不断增加:核心查询语句冗长,难以维护,且易引发慢查询。
- 表结构调整影响多个系统:修改 customer 表结构,需重编译并部署所有
JOIN 该表的业务服务。 - 主数据服务无法独立演进:LMS 服务想做分库分表或引入缓存,受限于业务库
JOIN 操作,无法实施。 - 数据一致性风险:业务库与主数据表存在数据同步延迟或丢失风险。
2.3 核心架构问题总结
- 紧耦合的数据库限制了微服务自治。
- 业务服务直接穿透到基础设施层(数据库)。
- 分布式事务隐患:虽然当前多为查询,但若存在跨库更新,极易产生数据不一致。
3. 改造目标
本次架构改造构建一个健壮、可扩展的主数据治理体系。
1 架构解耦 彻底消除业务服务 SQL JOIN 主数据表的行为,强制通过
wpglb-dms-basic API 访问
2 统一治理 所有主数据新增、修改、失效均在 dms-basic 内闭环
3 标准化 制定主数据模型标准(编码规则、字段长度、校验逻辑)
4 高性能 引入缓存( Redis)
4. 系统架构设计
4.1 改造前架构

问题:数据库成为中心化瓶颈,服务不独立。
4.2 改造后架构

优势:服务自治,通过 API 交互,底层存储变化不影响上层。
5. 主数据访问模式改造
5.1 原有模式(禁止)
<select id="queryOrderDetail" resultType="OrderVO">
SELECT ..., c.name as customerName
FROM t_order o
LEFT JOIN lms_customer c ON o.cust_id = c.id
</select>
严禁业务服务 JOIN 主数据表。
5.2 改造后模式
采用 查询 + 内存组装。
步骤:
- 查询订单主数据
- 提取主数据ID
- 调用 basic 批量接口
- 内存组装
示例代码:
OrderDTO order = orderMapper.selectById(orderId);
Long customerId = order.getCustomerId();
Result<List<CustomerDTO>> result =
basicCustomerApi.batchQueryByIds(Collections.singletonList(customerId));
CustomerDTO customer = result.getData().get(0);
order.setCustomerName(customer.getName());
5.3 批量接口设计
@FeignClient(name = "wpglb-dms-basic", contextId = "basicCustomerApi")
public interface BasicCustomerApi {
@PostMapping("/api/dms/basic/customer/batch")
Result<List<CustomerDTO>> batchQueryByIds(@RequestBody List<Long> ids);
@PostMapping("/api/dms/basic/customer/batch-by-code")
Result<List<CustomerDTO>> batchQueryByCodes(@RequestBody List<String> codes);
}
性能要求:
- 单次请求 P99 < 100ms
- 支持批量 500 ID
6. 缓存与性能设计
主数据访问特点:
- 高频读取
- 低频更新
6.1 缓存架构
请求
↓
业务服务
↓
Redis Cluster
↓
MySQL6.2 缓存策略
读策略:
- Redis
- DB
写策略:
更新DB
↓
删除Redis6.3 Cache Key设计
格式:
dms:{domain}:{type}:{id}示例:
dms:customer:id:1001
dms:vehicle:code:粤B123457. 数据迁移策略
迁移分为四阶段:
阶段1:存量迁移
1 建表 dm_*
2 Schema对齐
3 Data全量同步
4 数据校验
阶段2:增量同步
使用 Canal / FlinkCDC
同步 Binlog → dms-basic
业务服务双写:
LMS
+
dms-basic阶段3:清理
1 停止双写
2 删除业务库主数据表
3 下线 LMS
4 清理代码依赖
4.指标监控
监控指标:
- 成功率 > 99.95%
- RT P99 < 200ms
- 缓存命中率 > 90%
5.回滚方案
触发条件:
- dms-basic不可用
- 下单失败率上升
回滚步骤:
- 回滚业务版本
- 恢复 LMS 调用
6. 风险控制
风险 解决方案
数据同步延迟 CDC监控
缓存雪崩 Redis集群
N+1调用 Batch接口
回滚风险 演练
7. 项目收益
- 数据解耦
- 提升研发效率
- 系统稳定性增强
- 数据资产沉淀
本次改造是物流平台向 中台架构演进的重要一步。
8.具体执行步骤:
1.迁移相关表到basic
2.迁移功能到basic
3.修改业务服务的feign接口为basic的接口
4.修改业务服务中,关联表查询的地方为basic的feign接口
5.全部修改完以后,测试移除业务库中主数据关联的包结构
6.验证所有服务是否通常(订单下单,web管理端,pda管理端)
7.测试进行全流程回归验证,
8.测试进行下单流程压力测试
9.上线basic试运行
10.同步主数据的数据到basic
11.数据双写, 主数据库和业务库进行双写同步
12.上线dms所有业务服务试运行,观察2-3天
13.生产验证主数据功能是否正常,功能是否正常
14.分步骤,按天移除生产业务库中的主数据表
15.当业务库的主数据表完全移除后,下线LMS服务。
16.观察业务服务运行状态。修复bug
17.结束项目
上线回滚方案:
1.业务版本切换回正常的release历史分支即可,
将主数据的表+数据 双写同步
最后编辑:陆飞 更新时间:2026-04-17 09:34