惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
I
InfoQ
小众软件
小众软件
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
大猫的无限游戏
大猫的无限游戏
美团技术团队
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
MongoDB | Blog
MongoDB | Blog
V
V2EX
J
Java Code Geeks
有赞技术团队
有赞技术团队
博客园 - 聂微东
B
Blog RSS Feed
博客园 - 司徒正美

博客园 - 荆棘人

AI的下一个战场,不在屏幕里,而在现实世界 mysql数据库update时1048 - Column 'other_ext' cannot be null MediatR和CAP结合使用,应清晰区分场景 saas系统定制业务 微服务,数据一致性 mysql中高效取子表数据第一条某个字段返回 .net解决分布式事务简单方案DotNetCore.CAP kubesphere记录 CanalSharp使用学习 漏洞扫描,编写功能,让接口多传参数就报错 调用WebService异常:提供的 URI 方案“https”无效,应为“http”。 (Parameter 'via') asp.net web api 接口内调用多个远程接口优化 asp.net web api 接口控制并发研究(临时性方法) angular-ui-router学习 使用Oracle SQL Developer连接Oracle数据库 element ui <el-form-item>文字太长换行怎么办? element ui 如何在一行放置三个输入框和两个按钮 javascript中的iframe JavaScript的一些特殊语法 学习angularJS笔记
微服务中数据一致性问题
荆棘人 · 2025-12-29 · via 博客园 - 荆棘人

国际物流和3PL仓储业务,asp.net core web api 系统,为了解决在一个业务方法内直接调用多个系统的接口,数据可能不一致(当某个接口调用失败时,导致没有通知到该系统),
还有接口很慢的问题(内部调用的第三方接口有点多),引入了CAP和Kafka。

方案一

保存业务数据时,插入多条message,对应多个topic:
1)CAP.Published 表会插入 4 条记录
2)每个系统订阅自己专属的 Topic
3)适合不同系统需要不同的消息结构或字段

 1 public async Task<bool> CreateFreightOrderHandle(CreateOrderCommand request, CancellationToken cancellationToken)
 2 {
 3     var order = new Order(...);
 4     await _orderRepository.AddAsync(order);
 5     
 6     // 发布 4 条消息到不同 Topic
 7     await _capPublisher.PublishAsync("order.created.v1.warehouse", new OrderCreatedEvent(...));
 8     await _capPublisher.PublishAsync("order.created.v1.billing", new OrderCreatedEvent(...));
 9     await _capPublisher.PublishAsync("order.created.v1.tracking", new OrderCreatedEvent(...));
10     await _capPublisher.PublishAsync("order.created.v1.notification", new OrderCreatedEvent(...));
11     
12     // 一次性提交:订单数据 + 4 条 Outbox 记录
13     await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken);
14     
15     return true;
16 }

方案二

 1 public async Task<bool> CreateFreightOrderHandle(CreateOrderCommand request, CancellationToken cancellationToken)
 2 {
 3     var order = new Order(...);
 4     await _orderRepository.AddAsync(order);
 5     
 6     // 只发布 1 条消息
 7     await _capPublisher.PublishAsync("order.created.v1", new OrderCreatedEvent(...));
 8     
 9     await _orderRepository.UnitOfWork.SaveChangesAsync(cancellationToken);
10     
11     return true;
12 }

消费方:

// 仓库服务
[CapSubscribe("order.created.v1", Group = "warehouse.service")]
public async Task HandleWarehouse(OrderCreatedEvent @event) { ... }

// 计费服务
[CapSubscribe("order.created.v1", Group = "billing.service")]
public async Task HandleBilling(OrderCreatedEvent @event) { ... }

// 物流跟踪服务
[CapSubscribe("order.created.v1", Group = "tracking.service")]
public async Task HandleTracking(OrderCreatedEvent @event) { ... }

// 通知服务
[CapSubscribe("order.created.v1", Group = "notification.service")]
public async Task HandleNotification(OrderCreatedEvent @event) { ... }

单topic特点:
1)CAP.Published 表只插入 1 条记录
2)Kafka 会自动把这条消息分发给 4 个 Consumer Group
3)减少数据库写入压力,更符合消息队列的设计理念

方案三

混合方案,解决特殊场景消息数据结构不一致问题

适合:系统正在快速迭代,业务变化频繁

// 核心事件用单 Topic + 向后兼容
await _capPublisher.PublishAsync("order.created.v1", new OrderCreatedEvent 
{
    OrderId = order.Id,
    Amount = order.Amount,
    // 只放核心通用字段
});

// 特殊需求用专属 Topic
if (order.NeedCustomsClearance) 
{
    await _capPublisher.PublishAsync("order.customs.required.v1", new CustomsEvent 
    {
        OrderId = order.Id,
        ClearanceCode = order.CustomsClearanceCode,
        Documents = order.CustomsDocuments
    });
}

多版本方案

// 发布端同时发两个版本
await _capPublisher.PublishAsync("order.created.v1", eventV1);  // 老系统继续用
await _capPublisher.PublishAsync("order.created.v2", eventV2);  // 新系统用新版

// 过渡期结束后,逐步下线 v1

优点:
1)完全隔离新老系统,零影响
2)适合多团队独立迭代
缺点:

1)过渡期需要维护两套消息(Outbox 表多一倍记录)
2)需要明确的下线时间表

注:文章内容由AI生成,仅做个人记录;