本地事务和分布式事务
远程服务假失败:
远程服务其实成功了,由于网络故障等原因没有返回导致服务回滚,数据库却发生改变
远程服务成功,其他方法出现问题,导致已执行的远程请求无法回滚
- @Transactional本地事务在分布式系统中,只能控制自己的回滚,控制不了其他事务的回滚
- 分布式事务:最大原因由于网络波动问题(无法确认远程调用是否是真失败还是假失败)+分布式机器(不操作一个数据库无法回滚)
注意:直接调用同一个类里面的事务方法会导致事务失效(即使设置事务的传播级别),因为aop的原因
解决无法同一个对象内互调事务失效问题
依赖版本由spring-boot控制
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
使用aop中的aspectj进行代理
开启aspectj代理功能,即使没有接口也可以创建代理
@EnableAspectJAutoProxy(exposeProxy = true)//暴露代理对象
代码实现
使用自定义名进行代理
需要代理的类名 自定义名 = (需要代理的类名)AopContext.currentProxy();
分布式事务
分布式中aop会根据raft算法进行机器领导选举(心跳机制,领导节点会一直和随从节点保持联系,随从节点只要接收到领导节点的信息就重置自旋时间,如果有两个节点同时自旋结束并且票数一致,就所有节点重新自旋),日志复制
分区展示:(分区最好为奇数)当分区间的联系中断,一个分区为2一个分区为3,有老领导的就继续跟着老领导,其他分区就开始选举新领导,当有客户开始像2个节点的分区提交数据的时候,领导开始日志复制,但是领导没有得到大多数节点的回复,数据就一直无法提交,而当有客户端向3个节点的分区就行提交数据的时候,3个分区的领导开始日志复制,由于3个分区的节点得到了大多数的回复,就开始保存数据,如果这时候两个分区之间的联系恢复,两个领导就会看谁的选举次数高就会让谁继续当新的领导然后其余节点同步新领导中的数据信息。如果分区为偶数,分区联系中断,这时客户端保持数据,集群为不可用状态
动画展示http://thesecretlivesofdata.com/raft/
cap原理中只可取cp或者ap但是某种业务下又必须要保证数据的一致性,于是对cap进行延伸BASE理论也就是弱一致性,即最终一致性。
分布式事务的解决方案
- 2PC模式
- 柔性事务-TCC事务补偿型
- 柔性事务-最大努力通知型方案
- 柔性事务-可靠消息+最终一致性方案(异步确保型)
问题:当我们在微服务事务状态中使用feign远程调用,当出现异常时,会出现本地事务回滚,远程调用事务不回滚,导致数据库信息异常,这个时候我们可以使用AEATA作为分布式事务的解决方案。
SEATA:https://seata.io/zh-cn/docs/overview/what-is-seata.html
在每一个微服务数据库创建一个回滚日志表
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT