seata数据一致性

场景:

seata AT模式二阶段回滚时,会进行一个数据校验:

拿 UNDO LOG 中的后镜像与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改,不会回滚。产生脏数据

解决方案:

方案一:选择seata XA模式(强一致性)

XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。

在第一阶段:TM会发送 Prepare 到所有参与分布式事务的RM询问是否可以提交操作,参与分布式事务的所有RM接收到请求,实现自身事务提交前的准备工作并返回结果。根据RM返回的结果,如果涉及分布式事务的所有RM都返回可以提交。

在第二阶段:则TM给RM发送commit的命令,每个RM实现自己的提交同时释放锁和资源,然后RM反馈提交成功,TM完成整个分布式事务;如果任何一个RM返回不能提交,则涉及分布式事务的所有RM都被告知需要回滚。

XA致命的缺点,那就是性能不理想,特别是在交易下单链路,往往并发量很高,XA无法满足高并发场景。阻塞性协议,增加响应时间、锁时间、死锁。

方案二:@GlobalLock + 人工处理(弱一致性)

1、提前预防 

找出程序中对该表有修改操作的方法,使用@GlobalLock添加全局锁,在执行本地事务时,去获取该数据的全局锁,如果获取不到,说明该数据正在被全局事务执行,可以进行重试获取。 

如在本地修改事务上加上@GlobalLock,配置重试间隔为100ms,次数为10次,说明在1S内会不断重试获取全局锁,如果该记录在全局事务中,则会失败。

因为开启全局事务@GlobalTransactional是一个比较重的操作,需要向 TC 发起开启全局事务等 RPC 过程,而@GlobalLock注解只会在执行过程中查询全局锁是否存在,不会去开启全局事务,因此在不需要全局事务,而又需要检查全局锁避免脏读脏写时,使用@GlobalLock注解是一个更加轻量的操作。

2、人工处理

当有些遗漏的情况下,没有使用@GlobalLock,导致二阶段混滚失败产生脏数据,我们需要根据undo_log表,将数据修改为正常状态,但是这种比较麻烦,需要梳理脏数据的原因,也影响业务实际运行。  

posted @ 2023-04-27 18:35  joel1889  阅读(299)  评论(0)    收藏  举报