物流主数据服务迁移与架构改造方案


1. 项目背景

随着公司物流业务规模持续增长,系统架构逐渐演进为多微服务体系。当前系统包含订单中心、物流管理系统、结算系统、移动终端系统等多个业务服务,各服务在运行过程中均需要访问物流主数据,例如客户、承运商、车辆、司机、线路、网点等信息。

目前这些主数据主要由 wpglb-lms-service
服务提供,但随着系统的发展,该服务逐渐暴露出一系列架构问题。

主要问题包括:

  1. LMS缺乏未来扩展性,并且定义不准确。
  2. 主数据访问方式不统一:部分服务直连 DB,部分通过
    LMS,部分硬编码字典,缺乏统一标准。
  3. 主数据治理能力不足:缺乏统一的数据标准、质量监控和生命周期管理。
  4. 服务扩展和维护成本不断增加: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';

这种模式造成的问题:

  1. 边界被破坏:业务逻辑与主数据强耦合,违反 DDD 原则。
  2. SQL复杂度不断增加:核心查询语句冗长,难以维护,且易引发慢查询。
  3. 表结构调整影响多个系统:修改 customer 表结构,需重编译并部署所有
    JOIN 该表的业务服务。
  4. 主数据服务无法独立演进:LMS 服务想做分库分表或引入缓存,受限于业务库
    JOIN 操作,无法实施。
  5. 数据一致性风险:业务库与主数据表存在数据同步延迟或丢失风险。

2.3 核心架构问题总结

  1. 紧耦合的数据库限制了微服务自治。
  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 改造后模式

采用 查询 + 内存组装

步骤:

  1. 查询订单主数据
  2. 提取主数据ID
  3. 调用 basic 批量接口
  4. 内存组装

示例代码:

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
 ↓
MySQL

6.2 缓存策略

读策略:

  1. Redis
  2. DB

写策略:

更新DB
 ↓
删除Redis

6.3 Cache Key设计

格式:

dms:{domain}:{type}:{id}

示例:

dms:customer:id:1001
dms:vehicle:code:粤B12345

7. 数据迁移策略

迁移分为四阶段:

阶段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不可用
  • 下单失败率上升

回滚步骤:

  1. 回滚业务版本
  2. 恢复 LMS 调用

6. 风险控制

风险 解决方案


数据同步延迟 CDC监控
缓存雪崩 Redis集群
N+1调用 Batch接口
回滚风险 演练


7. 项目收益

  1. 数据解耦
  2. 提升研发效率
  3. 系统稳定性增强
  4. 数据资产沉淀

本次改造是物流平台向 中台架构演进的重要一步

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-03-14 09:44
最后编辑:陆飞  更新时间:2026-04-17 09:34