在微服务架构里,最常见的坑是什么?不是服务发现,不是熔断降级,而是你以为数据库和消息队列一起操作就叫"分布式事务"。看一段代码:先保存订单,再发布"订单已创建"消息。保存成功了,发布失败了怎么办?订单存在,但下游服务永远不知道这件事发生。
这就是典型的"双重写入"反模式——两个操作缺乏原子性,部分失败直接导致数据不一致。手动补偿?逻辑复杂、容易出错,恢复难度大。今天不讲八股文,直接拆解两种成熟的解决方案,以及配套的最佳实践清单。
事务发件箱模式把消息当作业务数据的一部分,塞进同一个数据库事务里。订单落库时,一条待发送的事件记录同步写入发件箱表。事务提交成功,后台服务再从发件箱表里拣选、发送,发完后标记处理状态。实体很简单:消息ID、事件类型、载荷、创建时间、处理时间、重试次数、错误信息,能追踪每一条事件的完整生命周期。
生产环境落地需要盯住几个细节。后台服务得有完善的错误处理和重试逻辑,消费者端必须设计成幂等——同一条消息消费多次不产生副作用。要监控发件箱表大小,定期清理已处理消息,高流量场景下考虑分区。Entity Framework Core 9里实现起来不复杂,表结构定义清晰,DbContext把订单和发件箱两类实体纳入同一个上下文管理。
另一种思路叫变更数据捕获,直接在数据库层面捕获数据变动。Azure SQL Database内置CDC支持,变更追踪开启后就能捕获行级修改。但别想得太美:持续监控CDC对数据库的性能开销,合理配置保留期避免存储膨胀,表结构变更时要小心处理防止捕获中断,处理器故障恢复后能续传不丢数据。
Azure生态里打法更丰富。Azure Service Bus提供死信队列和定时消息保证送达可靠性;Azure Functions做轻量级CDC处理器适合无服务器场景;Cosmos DB变更源给NoSQL场景提供替代方案;Application Insights做端到端事务追踪;Durable Functions内置状态管理,实现Saga模式天然有优势。
不管你选哪条路,下面这套清单缺一不可。全面打日志、用分布式追踪串联跨服务操作、每一个环节都按幂等设计、提前规划故障场景和补偿动作。Azure Monitor加Application Insights做可观测性底座够用,关键是得做全。
别再直接双写了。数据库里加个发件箱表,或者接上CDC捕获,选一个落地,别让数据不一致逼死自己。
热门跟贴