背??景大家好,今天给大家分享一个2022年出门面试Java几乎必问的技术,那就是seata。什么??你才看了第一句话,心里就闪过无数个问号?因为你从未听说过seata?没关系。为了不让兄弟们出去面试被问到seata,会一头雾水。今天我们就来给大家解释一下。既然要告诉大家什么是seata,那我就得先说说这个东西的定位。这个东西是现在流行的SpringCloudAlibaba中的一个组件,就是为了帮助我们解决分布式事务问题而设计的。也就是说,seata是一个分布式事务框架。什么是分布式事务?很多小伙伴可能会一头雾水。什么是分布式事务?好了,为了保证大家能够继续看下去,我们先来说说什么是分布式事务。举个最简单的例子,假设你负责一个订单系统,一个库存系统,一个营销系统。那么,当你的订单系统收到用户创建订单的请求时,这时候你要做三件事。事情。一是调用库存系统的接口锁定库存,二是调用营销系统的接口锁定优惠券,三是你的订单系统要往MySQL里面插入一系列的订单数据。比如如下图1所示:那么现在问题来了,你的订单系统有自己的订单数据库,可以插入订单数据,那么库存系统是不是也应该有自己的库存数据库来锁定库存数据呢?营销系统不应该有自己的营销数据库,锁定优惠券吗?当然!每个人都有自己的数据库,这个一定是。如下图2所示:现在问题又来了。由于创建订单的请求涉及到订单、库存、营销三个系统,因此只能通过操作各自的三个数据库来完成请求。有没有可能会出现这种情况,首先你先调用库存系统,库存被锁定,O。然后,你又调用营销系统,锁定优惠券,O。最后,当你的订单系统要向你的订单数据库插入数据的时候,网络抽风,导致你这次插入订单数据失败,直接异常,搞得你一头雾水。如下图3所示:你认为此时可能会出现什么样的问题?其实很简单。此时该订单中您要购买的商品库存已被锁定。已被锁定。结果你这个订单的数据本身并没有进入数据库,然后给用户返回了一个异常信息说这次下单失败。但是如果你说订单失败,它就会失败。因此,操作在查看库存数据时可能会感到困惑。为什么有些商品库存被锁定,却没有相应的订单,也没有人付款购买?什么???那么用户也有点疑惑,因为自己查看了自己的优惠券,好不容易省了几张买东西的优惠券,但是现在还没有下单,优惠券的状态已经被使用了。立即使用这些优惠券。如下图4所示:其实这是一个非常经典的分布式事务问题。您创建订单的请求跨越订单、库存、营销三个系统,分别涉及三个数据库。很有可能你会发现你的库存和营销数据操作成功了,库存和营销数据库中的本地交易都被提交了。导致订单插入数据库失败,订单数据库本地事务回滚,但库存和营销数据库本地事务已经提交,不会回滚。如下图5所示:什么是反向补偿?既然问题已经找到了,我们应该期待什么效果呢?我们其实希望的效果是,如果订单入库失败,回滚订单数据库的本地事务,我们应该想办法通知库存系统和营销系统,做一个反向补偿针对之前在库存库和营销库提交的数据修改,恢复。什么是反向补偿?也就是说,如果库存系统之前在数据库中执行了insert,那么此时应该执行delete,删除之前插入的数据。如果之前执行过delete,现在应该执行insert,重新插入删除的数据。如果之前执行过udpate语句,现在应该再次执行update语句,将数据恢复到更新前的状态。如下图6所示:seata,网上最流行的分布式事务组件,既然我们要实现这个效果,这个时候就出现了一个问题。我们不能单靠自己解决这个问题。这时候就必须引入SpringCloud阿里巴巴中的boss组件,seata。Seata就是为了帮助我们解决这个问题而设计的。如果我们在系统中引入seata框架,seata实际上会嵌入到每一个系统中,我们还需要部署一个seataserver。如下图7所示:这时我们系统的运行原理会变成这样:订单系统中的seata会向seata服务器发送请求,启动全局交易,然后库存系统先运行。当它在进行数据库CRUD时,这些操作会被seata框架拦截。然后seata框架会在一个本地事务中将你的sql语句和反向补偿日志一起插入到你的库存数据库中。inventory数据库中必须有一张undo_log表,用于存放seata的反向补偿日志。那么这个反向补偿日志是什么呢?简单,如果你的sql是insert,那么反向补偿日志可以帮你建一个delete语句去删除,如果你的sql是update,那么反向补偿日志可以记录你更新前的旧数据数据,他可以帮你更新稍后将数据恢复为旧版本的状态。如下图8所示:你的库存系统的sql语句和他们的补偿日志是在一个本地事务中一起提交的,一起成功或者一起失败,所以每当你的库存系统更新成功的时候,必然有一个相应的补偿日志是也保存在库存数据库中以备不时之需,营销系统的工作原理相同。然后假设库存系统和营销系统都按照这个思路实现了,到了订单系统,他最后pick了,插入订单数据库失败了。当然在插入的时候,其实会有相应的补偿日志一起提交,但是此时因为网络问题,插入订单和插入补偿日志会一起失败。那么这个时候订单系统的seata就会向seata服务器上报说,兄弟,我这边完了,你还不通知库存和营销兄弟,做反向补偿。如下图9所示:然后seata服务器发现分布式事务失败了,赶紧的,他会通知库存系统和营销系统的seata框架。小弟说,兄弟们,抓紧时间,把之前在数据库中的undo_log表中取出补偿日志,建一个反向补偿sql。如果之前是insert,你应该给我做一个delete,如果之前是delete,你应该给我做一个insert,如果之前是update,你还是应该做一个update,反向补偿sql快速运行,恢复数据给我,把前队换成后队,往前跑,快点。如下图10所示:总结的很棒。至此,我们就发现了seata的老大这个角色。您的订单、库存和营销系统随意运行。如果有人失败了,seataserver会收到你的失败通知。,会告诉其他系统使用undolog日志建立补偿sql,回滚所有数据,完美。
