一、事务
1、事务的四大特性
原子性:事务执行必须是整体不可分割的。事务中的所有操作,要么全部成功,要么全部失败。
一致性:要保证数据库内部完整性约束、声明性约束。
隔离性:对同一资源操作的事务不能同时发生。
持久性:对数据库做的一切修改将永久保存,不管是否出现故障。
2、事务的传播机制
测试注意事务失效场景
1、第一种 Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。
2、第一种 Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。
3、事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。
1、PROPAGATION_REQUIRED(默认事务传播机制)
定义:如果当前没有事务,就新建一个事务。如果当前有事务,就加入当前事务里面。
案例1:
一个大的事务X,调用了A,B个事务,A,B两个事务是PROPAGATION_REQUIRED。
方法order1,addUser,updateUser三个方法归纳为一个事务。任意一个方法异常,都会回滚。
案例2:
一个大方法非实物,调用了A,B个事务,A,B两个事务是PROPAGATION_REQUIRED。
方法addUser,updateUser这两个方法是两个独立事务方法,但是二者之间的事务相互不影响。但是此时由于我们下面代码是本类的方法调用,导致事务全部失效
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@PostMapping("/order1")
@Transactional
public void order1(){
// 新增方法
addUser();
// 修改方法
updateUser();
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser() {
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
int i = 1 /0;
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void addUser() {
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
}
案例2---解决方案,代理。
方案1、 使用@Autowired注解或者@Resource注解注入自己,然后使用注入的代理类去调用事务方法。(Spring循环依赖解决自己调用自己的依赖问题)
方案2、使用BeanFactory 获取对象。
TranSaltionController tranSaltionController = (TranSaltionController) beanFactory.getBean("tranSaltionController");方案3、在类上面添加注解@EnableAspectJAutoProxy(exposeProxy = true),然后在类中获取当前类的代理类,使用代理类调用事务方法。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
// @Transactional
public void order1(){
// TranSaltionController tranSaltionController = (TranSaltionController) beanFactory.getBean("tranSaltionController");
// TranSaltionController tranSaltionController = (TranSaltionController)AopContext.currentProxy();
// 新增方法
tranSaltionController.addUser();
// 修改方法
tranSaltionController.updateUser();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
throw new NullPointerException();
}
}
2、PROPAGATION_SUPPORTS
定义:支持当前事务,当时若没有事务,就以非事务方法运行。
案例1:
一个大的事务方法X,包含两个小的事务方法A,B。A,B两个事务方法机制是PROPAGATION_SUPPORTS。
此时,如果三个方法任意一个方法发生异常,都会发生事务回滚。
案例2:
一个大的方法无事务,包含两个小的事务方法A,B。A,B两个事务方法机制是PROPAGATION_SUPPORTS。
此时,如果发生异常,相当于是一个三个无事务方法,不存在事务回滚情况。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
// @Transactional
public void order1(){
// TranSaltionController tranSaltionController = (TranSaltionController) beanFactory.getBean("tranSaltionController");
// TranSaltionController tranSaltionController = (TranSaltionController)AopContext.currentProxy();
// 新增方法
tranSaltionController.addUser();
// 修改方法
tranSaltionController.updateUser();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.SUPPORTS)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.SUPPORTS)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
throw new NullPointerException();
}
}
3、 PROPAGATION_MANDATORY
定义:当前方法有事务,加入当前事务。当前方法无事务,报错。
以上三个方法,属于事务支持类的传播机制。
4、PROPAGATION_REQUIRES_NEW
定义:如果当前方法有事务,将这个事务挂起,自己新建事务独立运行。当前无事务,新建事务独立运行。
也就是说,当前有事务,无事务一样效果。都是各自使用各自的事务运行。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
// @Transactional
public void order1(){
// TranSaltionController tranSaltionController = (TranSaltionController) beanFactory.getBean("tranSaltionController");
// TranSaltionController tranSaltionController = (TranSaltionController)AopContext.currentProxy();
// 新增方法
tranSaltionController.addUser();
// 修改方法
tranSaltionController.updateUser();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
throw new NullPointerException();
}
}
5、PROPAGATION_NOT_SUPPORTED
定义:当前方法无事务的话,以非事务方法运行。有事务的话,将当前事务挂起,还是以非事务方法运行。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
@Transactional
public void order1(){
// 新增方法
tranSaltionController.addUser();
// 删除方法
tranSaltionController.updateUser();
User user = User.builder()
.id(11L)
.username("刘登辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
throw new NullPointerException();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
}
}
6、PROPAGATION_NEVER
定义:当前方法存在事务,直接报错。当前方法不存在事务,以非事务方法运行。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
// @Transactional
public void order1(){
// 新增方法
tranSaltionController.addUser();
// 删除方法
tranSaltionController.updateUser();
// User user = User.builder()
// .id(11L)
// .username("刘登辉")
// .address("万荣县王显乡")
// .build();
// transactionMapper.insertUser(user);
//
// throw new NullPointerException();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.NEVER)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.NEVER)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
throw new NullPointerException();
}
}
以上三个方法,属于事务不支持类的传播机制。
7、PROPAGATION_NESTED
定义:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
嵌套事务---不同之处,子事务报错,只影响本身。父事务抛异常,父子事务均回滚。
案例1,无事务情况。此时只有修改这个事务会回滚,别的事务不会受影响。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
@Transactional
public void order1(){
User user = User.builder()
.id(11L)
.username("刘登辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
// 新增方法
tranSaltionController.addUser();
// 删除方法
tranSaltionController.updateUser();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.NESTED)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.NESTED)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
try {
throw new NullPointerException();
}catch (Exception e){
//手动强制回滚事务,这里一定要第一时间处理
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}
此时如果是PROPAGATION_REQUIRED,大家是一个整体事务。一荣俱荣一损俱损。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@PostMapping("/order1")
@Transactional
public void order1(){
User user = User.builder()
.id(11L)
.username("刘登辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
// 新增方法
tranSaltionController.addUser();
// 删除方法
tranSaltionController.updateUser();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
try {
throw new NullPointerException();
}catch (Exception e){
//手动强制回滚事务,这里一定要第一时间处理
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}
8、总结
类型 | 说明 |
PROPAGATION_REQUIRED | 当前存在事务,就归纳到这个事务里面。 当前不存在事务,就新建事务,各自事务方法独立运行。 |
PROPAGATION_SUPPORTS | 当前存在事务,就归纳到这个事务里面。 当前不存在事务,就以非事务运行,现象就是整体无事务 |
PROPAGATION_MANDATORY | 当前存在事务,就归纳到这个事务里面。 当前不存在事务,就直接报错 |
PROPAGATION_REQUIRES_NEW | 当前存在事务,将这个事务挂起。新建事务,各自事务方法独立运行。 当前不存在事务,就新建事务,各自事务方法独立运行。 |
PROPAGATION_NOT_SUPPORTED | 当前存在事务,就将这个事务挂起。以非事务方法运行。 当前不存在事务,以非事务方法运行。 |
PROPAGATION_MANDATORY | 当前存在事务,直接报错。 当前不存在事务,以非事务方法运行。 |
PROPAGATION_NESTED | 当前存在事务,嵌套事务。子回滚父不回滚,父回滚子回滚。 当前不存在事务,和PROPAGATION_REQUIRED一样。 |
3、分布式事务的案例
微服务下单业务,在下单时会调用订单服务,创建订单并写入数据库。然后订单服务调用账户服务和库存服务: 账户服务负责扣减用户余额 库存服务负责扣减商品库存。
在分布式系统下,一个业务跨越多个服务或数据源,每个服务都是一个分支事务,要保证所有分支事务最终状态一致,这样的事务就是分布式事务。
如果是分布式事务,分属于不同的库,此时库存服务失败之后,只会回滚库存服务数据,不会回滚订单服务和账户服务的数据。
案例1:
两个服务,A服务和B服务,分别调用不同的数据库。
A服务调用B服务。
A服务数据库写操作成功,B服务数据库写操作成功,此时A服务失败,由于事务回滚,此时A服务的写操作回滚,但是B服务数据库写操作不会成功。
案例2:
两个服务,A服务和B服务,分别调用相同的数据库。
A服务调用B服务。
A服务数据库写操作成功,B服务数据库写操作成功,此时A服务失败,由于事务回滚,此时A服务的写操作回滚,但是B服务数据库写操作不会成功。
package com.hihonor.transaltion;
import com.hihonor.bean.User;
import com.hihonor.mapper.TransactionMapper;
import com.hihonor.service.OpenFeginService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/Transactional")
public class TranSaltionController {
@Autowired
private TransactionMapper transactionMapper;
@Autowired
private AddUserController addUserController;
@Autowired
private UpdateUserController updateUserController;
@Autowired
private TranSaltionController tranSaltionController;
@Autowired
private BeanFactory beanFactory;
@Autowired
private OpenFeginService openFeginService;
@Autowired
private RestTemplate restemplate;
@PostMapping("/order2")
@Transactional
public void order2(){
// 新增方法
tranSaltionController.addUser();
// 修改方法
tranSaltionController.updateUser();
// String url ="http://userservice/orderService/updateOrder";
// restemplate.getForObject(url, User.class);
openFeginService.updateOrder();
throw new NullPointerException();
}
/**
* 新增用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void addUser() {
System.out.println("开始新增............");
User user = User.builder()
.id(10L)
.username("刘晓辉")
.address("万荣县王显乡")
.build();
transactionMapper.insertUser(user);
}
/**
* 修改用户信息方法
*/
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser() {
System.out.println("开始修改............");
User user = User.builder()
.id(10L)
.username("刘晓辉修改1")
.address("万荣县王显乡修改1")
.build();
transactionMapper.updateUser(user);
}
}
由此这个案例可知,我们常规的事务回滚无法处理跨服务和跨数据库的事务操作。但是在我们微服务之间的调用在我们项目中是十分常见的,要处理这种情况。就涉及到了 分布式事务的处理。
分布式事务的处理,从和我们事务传播的机制角度来讲,就是在事务和事务之间建立起连接关系,将不同的事务归纳为一个大的事务,成功都成功,失败都失败。
根据多事务汇总思路,业界提出的观点是--CPA理论,BASE理论。
4、CAP理论
4.1CAP定理
Consistency(一致性)
Availability(可用性)
Partition tolerance (分区容错性)
Eric Brewer 说,分布式系统无法同时满足这三个指标。这个结论就叫做 CAP 定理。
Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致
Availability (可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝
Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。
Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务 。
总结:
分布式系统节点通过网络连接,一定会出现分区问题(P)。
当分区出现时,系统的一致性(C)和可用性(A)就无法同时满足。
CPA:
我们的系统里面的分区和网络问题是不可能解决的。所以一定要存在分区容错性。
如果我们要保证一致性,此时那么A服务调用B服务的时候,假设B服务宕机了,此时如果要保证一致性,此时就需要一直等待B服务重新启用,此时可能会由于等待超时,而失败,这就丧失了可用性了。
如果我们要保证可用性。此时那么A服务调用B服务的时候,假设B服务宕机了,此时如果要保证可用性,那次是发现B服务宕机之后,可以返回旧数据,即便不是最新的数据,起码保证我们此次调用成功。
elasticsearch集群是CP还是AP?
ES集群出现分区时,故障节点会被剔除集群,数据分片会重新分配到其它节点,保证数据一致。因此是低可用性,高一致性,属于CP。
4.2BASE理论
BASE理论是对CAP的一种解决思路,包含三个思想:
Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
BASE 理论更多的是对CPA理论的一种补充。在保证可用性的同时,兼顾了数据一致性问题。也就是说在一定时间内可以出现数据不一致的情况,但随着时间推移最终还是要保证数据一致性,也就是允许存在过渡时间来完成数据的同步。
4.3分布式事务理论
而分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:
AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。
BASE理论:基本可用,软状态,最终一致。
分布式事务模型
我们之前说了,分布式事务就是多个事务组成一个大事务,但是数据库和数据库之间,服务和服务之间是无法相互通信的,所以我们要做一个可以和各个服务之间通信的事务协调者,由它来通知各个服务是进行事务的回滚还是事务的提交。
各个服务的事务,称为子事务。子事务共同组成一个主事务。
解决分布式事务的思想和模型
全局事务:整个分布式事务。
分支事务:分布式事务中包含的每个子系统的事务。
最终一致思想:各分支事务分别执行并提交,如果有不一致的情况,再想办法恢复数据。
强一致思想:各分支事务执行完业务不要提交,等待彼此结果。而后统一提交或回滚。
5、分布式中间件Seata
5.1简介
Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务,为用户打造一站式的分布式解决方案。
官网地址:http://seata.io/,其中的文档、播客中提供了大量的使用说明、源码分析。
5.2seata架构
Seata事务管理中有三个重要的角色:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata提供了四种不同的分布式事务解决方案:
XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
TCC模式:最终一致的分阶段事务模式,有业务侵入
AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
SAGA模式:长事务模式,有业务侵入
5.3stata的部署和集成
Docker启动安装nacos(详情讲解,全网最细)_docker启动nacos-CSDN博客
Docker 安装Seata 并注册进Nacos_seata注册失败 docker_Cadence_D的博客-CSDN博客