REST微服务的分布式事务实现微服务的分布式事务实现-分布式系统、事务以及分布式系统、事务以及JTA介介
绍绍
事务,是操作数据库中的数据的逻辑单元。在处理一个业务过程中,事务保证多个数据修改的操作,要么都修改成功,要么都
失败。同时,几个事务之间又相互独立,不会相互影响。
事务的ACID原则
在介绍分布式事务之前,先来来回顾一下事务的ACID原则:
原子性(A):原子性是指一个事务的所有操作,要么都做完,要么都不做。
一致性(C):一致性是指一个事务的执行,不管外部环境如何,不管怎么执行,结果应该都是一致的。
隔离性(I):隔离性是指几个事务在同时执行的时候,相互之间不会受影响。
持久性(D):持久性就是事务完成以后,数据就被保存。
那么,在分布式系统中,这个原则是否能够保证呢?答案是不能,Not even close! 以原子性为例,在有多个系统的分布式系
统中,一个分布式事务是在不同的系统内部执行的,我们没有办法保证它们能够同时完成,或者都不做。至于分布式事务的原
则,我们过一会再说,我们先把事务搞清楚。
Spring中使用事务
Spring是一个伟大的框架,从一开始只是一个容器框架,到现在已经发展成为了一个包含企业开发中的方方面面的很多框架的
总称。它不但从复杂度上,发展出了用于各个方面的子框架。它还从易用性出发,推出了像Spring-Boot这样的框架,使得搭
建环境变得异常的简单。
很早之前Spring就已经有了一套自己的事务规范。(在org.springframework.transaction包中),而且用起来也非常的简单:
@Service
public Class OrderService {
@Transactional
public TicketOrder buyTicket(OrderDTO orderDTO) {
TicketOrder tkOrder = new TicketOrder();
jdbcTemplate.execute(createOrderSQL);
return tkOrder;
}
}
我们只需要在方法上加一个Transactional标签,那个这个方法就会在一个事务里面执行。这是用代理模式实现的。Spring容器
在初始化这个service实例的时候,实际上是创建一个代理类,然后在调用这个方法的时候,包装一个事务的处理。上面的方
式使用代理模式展开,大致如下:
public Class OrderServiceProxy {
// 通过代理实现的伪代码,在原先的代码外再包一层事务的创建、
commit、rollback
public Order buyTicket(OrderDTO orderDTO) {
// get transaction from entityManager
theTransaction.begin();
try {
orderServiceImpl.buyTicket(orderDTO)
theTransaction.commit();
} catch(Exception e) {
theTransaction.rollback();
throw e;
}
}
}
从这个流程可以看出,在更改数据的时候jdbcTemplate.save(order),事务并没有提交,用户查看最新的数据的时候,也看不
到这条数据(隔离性),只有commit以后,所有的数据修改才会同时起效(原子性)。如果期间发生任何错误,事务就会回
退rollback,所有的数据修改又回到未修改状态。