如何为MassTransit事务性发件箱与收件箱配置乐观并发控制(MSSQL)
MassTransit事务性发件箱/收件箱配置乐观并发控制(MSSQL)
MassTransit的事务性发件箱、收件箱完全支持用乐观并发控制替代锁,能和你现有基于乐观并发的数据库事务无缝整合,具体实现步骤如下:
1. 给MSSQL的发件箱/收件箱表加并发令牌
MSSQL里用RowVersion(自动更新的timestamp类型)作为并发令牌最合适。如果是用MassTransit自带的迁移脚本,需要修改脚本给两张表加字段:
OutboxMessage表:新增RowVersion TIMESTAMP NOT NULL字段InboxMessage表:同样新增RowVersion TIMESTAMP NOT NULL字段
2. 配置MassTransit启用乐观并发
在注册MassTransit的代码里,明确指定发件箱、收件箱使用乐观并发控制,示例代码如下:
services.AddMassTransit(x => { x.SetKebabCaseEndpointNameFormatter(); x.UsingSqlServer((context, cfg) => { cfg.Host("你的MSSQL连接字符串"); cfg.ConfigureEndpoints(context); // 配置发件箱用乐观并发 cfg.UseTransactionalOutbox(context, outboxCfg => { outboxCfg.UseSqlServer(); outboxCfg.UseOptimisticConcurrencyControl(r => r.RowVersion); }); // 配置收件箱用乐观并发 cfg.UseInbox(context, inboxCfg => { inboxCfg.UseSqlServer(); inboxCfg.UseOptimisticConcurrencyControl(r => r.RowVersion); }); }); });
3. 把消息发送纳入业务乐观并发事务
只需要保证业务事务和发件箱操作共用同一个数据库连接或者事务范围:
- 比如在你的业务服务里,用
IDbContextTransaction或者TransactionScope包裹业务操作和消息发送代码 - 一旦业务事务因为乐观并发冲突(比如抛出
DbUpdateConcurrencyException)回滚,发件箱里的待发消息也会跟着回滚,不会被发送出去
4. 处理并发冲突场景
当MassTransit处理发件箱/收件箱遇到乐观并发冲突时,会自动触发重试(你可以通过Retry配置调整重试次数、间隔策略)。另外你也可以在业务代码里捕获ConcurrencyException,根据业务需求做自定义处理。
内容的提问来源于stack exchange,提问作者user2953224
相关产品推荐
相关产品推荐

