由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

分布式事务之XA方案(Seata实现)

架构设计 西门飞冰 4058℃
[隐藏]

1.什么是XA?

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing) 标准。

典型的二段式事务解决方案

在 Seata 定义的分布式事务框架内,利⽤事务资源(数据库、消息服务等)对 XA 协议的⽀持, 以 XA 协议的机制来管理分⽀事务的⼀种事务模式。

XA方案作为业界的一种分布式事务的标准,主流的关系型数据库,Mysql、Oracle、PgSql等对他都有良好的支持。所以在我们开发的时候,只要是这个数据库支持XA方案,Seata就可以支持这个数据库并提供相应的服务。

2.Seata体系三个角色

事务管理器(TM):划分事务的边界范围,决定什么时候全局提交/回滚(司令官)

事务协调者(TC):负责通知命令的中间件Seata-Server(传令官)

资源管理器(RM):做具体事儿的工具人(大头兵)

3.XA的执行过程

3.1.场景说明

如下是一个商城项目:BussinessService表示商城入口是TM服务,OrderService表示订单服务,AccountService表示库存服务是RM服务。

3.2.阶段1

(1)TM在启动的时候,创建订单之前,会自动的向TC发起一个请求注册全局事务,说明要开始干活了

(2)TM 远程调用RM端的OrderServer,完成订单创建的操作,OrderServer在进行数据写入数据库前会自动的和TC完成一个分支事务,随后执行insert into语句,但是并没有实际的提交

(3)TM 远程调用RM端的AccountService完成扣减余额的操作,AccountService在进行数据更新数据库前会自动的和TC完成一个分支事务,随后执行update语句,但是并没有实际的提交

(4)当TM远程调用两个方法都处理成功之后,阶段1就处理完成了,开始进入第二个阶段

image-20221022211338344

3.3.阶段2

分支一:两个都处理成功

(1)TM向TC下达全局提交指令,然后TC主动的向两个RM端推送commit命令

(2)RM端收到commit命令之后,完成刚才的sql语句提交,这样就保证了整体的一致性

分支二:存在处理失败的情况

(1)TM向TC下达全局回滚指令,然后TC主动的向两个RM推送rollback命令

(2)RM端收到rollback命令之后,回滚刚才的sql语句

image-20221022211414184

因为整个过程所有的处理都是基于数据库的事务特性来完成的,所以可以保证数据库整体的原子性,要么数据全部提交,要么数据全部回滚,这是XA方案的一个优势所在,可以保证数据的强一致。

4.代码示意

TM端:BussinessService规定事务边界

public class BussinessService {
    @GlobalTransactional	//Seata独有的注解,表示开启全局事务,自动向TC下达指令
    public void purchase(String userId, String commodityCode, int orderCount,int money, boolean rollback) {
        //账户余额减少
        String result = accountFeignClient.reduce(userId, money);
        //向Order服务调⽤创建订单
        result = orderFeignClient.create(userId, commodityCode, orderCount);
    }
}

purchase方法执行成功,自动进入XA的二阶段,向TC下达全局提交的命令,中间执行失败,则向TC下达全局回滚的命令。这个过程完全由@GlobalTransactional注解完成,无需要额外控制

RM1:OrderService完成创建订单

对原有数据源进行扩展:Seata通过DataSourceProxyXA包装原⽣DataSource⾃动实现全局事务控制,包括分支事务的注册以及控制分支事务的提交或者回滚

@Configuration
public class OrderXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
        // return new DataSourceProxy(druidDataSource);
        // DataSourceProxyXA for XA mode
        return new DataSourceProxyXA(druidDataSource);
    }
}

OrderService实现业务⽅法:使用标准的声明式事务@Transactional,描述业务方法,执行insert语句就可以了

@Service
public class OrderService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Transactional
    public void create(String userId, String commodityCode, Integer count) {
        int orderMoney = count * 100;
        // ⽣成订单
        jdbcTemplate.update("insert order_tbl(user_id,commodity_code,count,money) values(?,?,?,?)",
        new Object[] {userId, commodityCode, count, orderMoney});
    }
}

RM2:AccountService完成账户余额扣减

配置部分和RM1一致

@Configuration
public class AccountXADataSourceConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }
    @Bean("dataSourceProxy")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
        // return new DataSourceProxy(druidDataSource);
        // DataSourceProxyXA for XA mode
        return new DataSourceProxyXA(druidDataSource);
    }
}

Transactional实现业务⽅法

@Service
public class AccountService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Transactional
    public void reduce(String userId, int money) {
        //减少余额
        jdbcTemplate.update("update account_tbl set money = money - ? where user_id = ?", new Object[] {money, userId});
    }
}

5.XA的优势

基于CP设计,强⼀致性,不会出现状态不⼀致

主流关系数据库都对XA有⽀持,数据业界标准

⼆段提交实现简单粗暴,成熟稳定

6.XA的劣势

执⾏效率低,所有操作都是基于数据库事务处理,数据没有被提交前会被hang住阻塞,⾼并发系统禁⽤

协议阻塞,在我们进行数据处理的时候,底层建立的是一个长链接,长连接建立后,在收到 XA commit 或 XA rollback 前必须阻塞等待,对网络连接利用率也是一个问题,如果⼀个参与全局事务的资源 “失联” ,其他RM资源会hang住,等待超时回滚,导致性能进⼀步下降

强制要求数据库特性⽀持XA,不⽀持的就没法⽤

7.适⽤场景

⾦融⾏业,并发量不⼤,但数据很重要的项⽬

其实XA适⽤于绝⼤多数企业及应⽤,哪里有那么多高并发事务写入场景。

转载请注明:西门飞冰的博客 » 分布式事务之XA方案(Seata实现)

喜欢 (4)or分享 (0)