幂等性检查与修复报告
任务编号: 2.4
执行时间: 2026-04-05
涉及服务: order-service, inventory-service, logistics-service
一、检查结果
1.1 订单创建 POST /api/orders/pull
- 检查结果: ❌ 无幂等性保护
- 问题描述: 重复调用
pullOrders / createOrders 会重复创建订单
- 现有字段:
platformOrderSn(平台订单号)存在,但无唯一约束和去重逻辑
1.2 库存扣减 POST /api/stock/deduct
- 检查结果: ❌ 无幂等性保护
- 问题描述: 网络重试导致重复扣减,可能出现库存为负数
- 现有保护: 乐观锁
@Version 仅防止并发覆盖,不防止重复请求
1.3 发货回传 POST /api/logistics/callback/{carrier}
- 检查结果: ⚠️ 部分幂等(轨迹去重,无运单状态幂等)
- 问题描述: 同一运单状态更新回调重复处理,可能导致状态回退
- 现有保护:
logisticsTraceMapper.countExist() 对轨迹有去重,但运单状态更新无幂等
1.4 消息队列消费者
- 检查结果: ℹ️ 无 MQ 消费者
- 说明: 系统使用 Spring Event(
StockChangedEventListener)实现异步,非传统 MQ
二、修复方案
2.1 订单服务(order-service)
新增文件
| 文件 |
说明 |
service/impl/OrderIdempotencyService.java |
Redis 幂等性工具类 |
修改文件
| 文件 |
修改内容 |
service/impl/OrderServiceImpl.java |
注入 OrderIdempotencyService,修改 createOrders() 和 shipOrder() 添加幂等检查 |
幂等键设计
订单创建:order:idempotent:{platform}:{shopId}:{platformOrderSn}
订单发货:order:idempotent:ship:{orderId}
修复逻辑
- Redis 检查:请求到达时先查 Redis 是否有处理记录
- DB 兜底:数据库唯一约束
uk_orders_platform_order_sn(platform_order_sn, platform, shop_id) 防止并发插入
- 幂等标记:处理成功后写入 Redis,TTL=24h
2.2 库存服务(inventory-service)
新增文件
| 文件 |
说明 |
service/impl/StockIdempotencyService.java |
Redis 幂等性工具类 |
修改文件
| 文件 |
修改内容 |
controller/StockFeignController.java |
注入 StockIdempotencyService,修改 deductStock() / lockStock() / unlockStock() 添加幂等检查 |
幂等键设计
扣减库存:stock:idempotent:{skuCode}:{warehouseId}:{relatedNo}
锁定库存:stock:idempotent:lock:{skuCode}:{warehouseId}:{relatedNo}
解锁库存:stock:idempotent:unlock:{skuCode}:{warehouseId}:{relatedNo}
修复逻辑
- Redis 检查:到达即查重
- 幂等响应:重复请求返回缓存结果而非错误,保证接口幂等
- DB 唯一索引:
uk_stocks_sku_warehouse(sku_code, warehouse_id) 防止库存记录重复
2.3 物流服务(logistics-service)
新增文件
| 文件 |
说明 |
service/impl/LogisticsIdempotencyService.java |
Redis 幂等性工具类 |
修改文件
| 文件 |
修改内容 |
service/TraceSyncService.java |
注入 LogisticsIdempotencyService,修改 processCallback() 添加幂等检查 |
幂等键设计
回调处理:logistics:idempotent:{carrierCode}:{waybillNo}:{status}:{latestTraceTime}
修复逻辑
- Redis 检查:同一运单同一状态回调在24h内不重复处理
- 轨迹去重:数据库已有
uk_logistics_trace_waybill_time_location 保障轨迹不重复
三、数据库变更(SQL Migration)
文件: docs/database/V2.4__idempotency_indexes.sql
-- orders 表:平台订单号+平台+店铺 唯一索引
ALTER TABLE orders
ADD CONSTRAINT uk_orders_platform_order_sn
UNIQUE (platform_order_sn, platform, shop_id);
-- stocks 表:SKU+仓库 唯一索引
ALTER TABLE stocks
ADD CONSTRAINT uk_stocks_sku_warehouse
UNIQUE (sku_code, warehouse_id);
-- logistics_trace 表:运单号+轨迹时间+地点 唯一索引
ALTER TABLE logistics_trace
ADD CONSTRAINT uk_logistics_trace_waybill_time_location
UNIQUE (waybill_no, trace_time, location);
四、幂等性保证层次
┌─────────────────────────────────────────────────────┐
│ 接入层 │
│ 幂等Token / 请求ID(可选,未来扩展) │
├─────────────────────────────────────────────────────┤
│ Redis 层 │
│ SETNX 原子操作防并发重复请求(TTL=24h) │
├─────────────────────────────────────────────────────┤
│ 数据库层 │
│ 唯一索引兜底:UK(platform_order_sn,platform,shop_id) │
│ UK(sku_code, warehouse_id) │
│ UK(waybill_no, trace_time, location) │
├─────────────────────────────────────────────────────┤
│ 业务层 │
│ 状态机 + 乐观锁防止状态异常 │
└─────────────────────────────────────────────────────┘
五、影响范围
| 接口 |
服务 |
幂等键 |
影响 |
POST /api/orders/pull |
order-service |
platform:shopId:platformOrderSn |
✅ 已修复 |
POST /api/orders/{id}/ship |
order-service |
ship:orderId |
✅ 已修复 |
POST /api/stock/deduct |
inventory-service |
skuCode:warehouseId:relatedNo |
✅ 已修复 |
POST /api/stock/lock |
inventory-service |
lock:skuCode:warehouseId:relatedNo |
✅ 已修复 |
POST /api/stock/unlock |
inventory-service |
unlock:skuCode:warehouseId:relatedNo |
✅ 已修复 |
POST /api/logistics/callback/{carrier} |
logistics-service |
carrier:waybillNo:status:traceTime |
✅ 已修复 |
六、注意事项
- Redis 连接:所有服务 pom.xml 均已包含
spring-boot-starter-data-redis,无需额外依赖
- 幂等TTL:统一设为 24 小时,可根据业务调整
- 数据库索引:执行 SQL migration 时注意在线表操作影响,建议在低峰期执行
- 消息队列:当前系统无 MQ 消费者(使用 Spring Event),无需额外处理
- 测试建议:使用 Postman/Curl 重复调用上述接口,验证幂等返回而非重复创建
七、修改文件清单
services/order-service/src/main/java/com/erp/order/service/impl/
+ OrderIdempotencyService.java [NEW]
services/order-service/src/main/java/com/erp/order/service/impl/OrderServiceImpl.java
[MOD] 添加 OrderIdempotencyService 依赖
[MOD] createOrders() 添加幂等检查
[MOD] shipOrder() 添加幂等检查
services/inventory-service/src/main/java/com/erp/inventory/service/impl/
+ StockIdempotencyService.java [NEW]
services/inventory-service/src/main/java/com/erp/inventory/controller/StockFeignController.java
[MOD] 添加 StockIdempotencyService 依赖
[MOD] deductStock() 添加幂等检查
[MOD] lockStock() 添加幂等检查
[MOD] unlockStock() 添加幂等检查
services/logistics-service/src/main/java/com/erp/logistics/service/impl/
+ LogisticsIdempotencyService.java [NEW]
services/logistics-service/src/main/java/com/erp/logistics/service/TraceSyncService.java
[MOD] 添加 LogisticsIdempotencyService 依赖
[MOD] processCallback() 添加幂等检查
docs/database/V2.4__idempotency_indexes.sql [NEW]
docs/幂等性修复报告.md [NEW]