那DTM是如何处理分布式事务的呢?以一个经典的跨行转账业务为例来看下事务处理过程。对于跨行转账业务而言,很显然是跨库跨服务的应用场景,不能简单通过本地事务解决,可以使用Saga模式,以下是基于DTM提供的Saga事务模式成功转账的的时序图:
从以上时序图可以看出,DTM整个全局事务分为如下几步:
基于以上这个时序图的基础上,再来看下DTM的架构:
整个DTM架构中,一共有三个角色,分别承担了不同的职责:
总体而言,AP-应用程序充当全局事务编排器的角色通过DTM提供的开箱即用的SDK进行全局事务和子事务的注册。TM-事务管理器接收到注册的全局事务和子事务后,负责调用RM-资源管理器来执行对应的事务分支,TM-事务管理器根据事务分支的执行结果决定是否提及或回滚事务。
百闻不如一见,接下来就来实际上手体验下如何基于DTM来实际应用Saga进行分布式跨行转账事务的处理。
接下来就来创建一个示例项目:
dotnet new webapi -n DtmDemo.Webapi
创建示例项目。Dtmcli
和Pomelo.EntityFrameworkCore.MySql
。
|
{ |
|
"dtm": { |
|
"DtmUrl": "http://localhost:36789", |
|
"DtmTimeout": 10000, |
|
"BranchTimeout": 10000, |
|
"DBType": "mysql", |
|
"BarrierTableName": "dtm_barrier.barrier", |
|
} |
|
} |
BankAccount
实体类:
|
namespace DtmDemo.WebApi.Models |
|
{ |
|
public class BankAccount |
|
{ |
|
public int Id { get; set; } |
|
public decimal Balance { get; set; } |
|
} |
|
} |
DtmDemoWebApiContext
数据库上下文:
|
using Microsoft.EntityFrameworkCore; |
|
|
|
namespace DtmDemo.WebApi.Data |
|
{ |
|
public class DtmDemoWebApiContext : DbContext |
|
{ |
|
public DtmDemoWebApiContext (DbContextOptions<DtmDemoWebApiContext> options) |
|
: base(options) |
|
{ |
|
} |
|
|
|
public DbSet<DtmDemo.WebApi.Models.BankAccount> BankAccount { get; set; } = default!; |
|
} |
|
} |
|
using Microsoft.EntityFrameworkCore; |
|
using DtmDemo.WebApi.Data; |
|
using Dtmcli; |
|
|
|
var builder = WebApplication.CreateBuilder(args); |
|
var connectionStr = builder.Configuration.GetConnectionString("DtmDemoWebApiContext"); |
|
// 注册DbContext |
|
builder.Services.AddDbContext<DtmDemoWebApiContext>(options => |
|
{ |
|
options.UseMySql(connectionStr, ServerVersion.AutoDetect(connectionStr)); |
|
}); |
|
|
|
// 注册DTM |
|
builder.Services.AddDtmcli(builder.Configuration, "dtm"); |
dotnet ef migrations add 'Initial'
创建迁移。BankAccountController
如下,其中PostBankAccount
接口添加了await _context.Database.MigrateAsync();
用于自动应用迁移。
|
using Microsoft.AspNetCore.Mvc; |
|
using Microsoft.EntityFrameworkCore; |
|
using DtmDemo.WebApi.Data; |
|
using DtmDemo.WebApi.Models; |
|
using Dtmcli; |
|
|
|
namespace DtmDemo.WebApi.Controllers |
|
{ |
|
[ | ]
|
[ | ]
|
public class BankAccountsController : ControllerBase |
|
{ |
|
private readonly DtmDemoWebApiContext _context; |
|
|
|
public BankAccountsController(DtmDemoWebApiContext context) |
|
{ |
|
_context = context; |
|
} |
|
[ | ]
|
public async Task<ActionResult<IEnumerable<BankAccount>>> GetBankAccount() |
|
{ |
|
return await _context.BankAccount.ToListAsync(); |
|
} |
|
|
|
[ | ]
|
public async Task<ActionResult<BankAccount>> PostBankAccount(BankAccount bankAccount) |
|
{ |
|
await _context.Database.MigrateAsync(); |
|
_context.BankAccount.Add(bankAccount); |
|
await _context.SaveChangesAsync(); |
|
|
|
return Ok(bankAccount); |
|
} |
|
} |
接下来定义SagaDemoController
来使用DTM的Saga模式来模拟跨行转账分布式事务:
|
using Microsoft.AspNetCore.Mvc; |
|
using Microsoft.EntityFrameworkCore; |
|
using DtmDemo.WebApi.Data; |
|
using DtmDemo.WebApi.Models; |
|
using Dtmcli; |
|
using DtmCommon; |
|
|
|
namespace DtmDemo.WebApi.Controllers |
|
{ |
|
[ | ]
|
[ | ]
|
public class SagaDemoController : ControllerBase |
|
{ |
|
private readonly DtmDemoWebApiContext _context; |
|
private readonly IConfiguration _configuration; |
|
private readonly IDtmClient _dtmClient; |
|
private readonly IDtmTransFactory _transFactory; |
|
|
|
private readonly IBranchBarrierFactory _barrierFactory; |
|
private readonly ILogger<BankAccountsController> _logger; |
|
|
|
public SagaDemoController(DtmDemoWebApiContext context, IConfiguration configuration, IDtmClient dtmClient, IDtmTransFactory transFactory, ILogger<BankAccountsController> logger, IBranchBarrierFactory barrierFactory) |
|
{ |
|
this._context = context; |
|
this._configuration = configuration; |
|
this._dtmClient = dtmClient; |
|
this._transFactory = transFactory; |
|
this._logger = logger; |
|
this._barrierFactory = barrierFactory; |
|
} |
|
} |
对于跨行转账业务,使用DTM的Saga模式,首先要进行事务拆分,可以拆分为以下4个子事务,并分别实现:
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!