Seata 进阶踩坑

之前的文章

seata简介及个人理解:分布式事务2PC TCC AT(Seata) 如何理解AT模式
seata单机的例子官网有,关于高可用部署往这看:保姆级配置 Seata1.2 + Nacos

并发异常

Seata AT模式下针对同一个数据在并发情况下,如果先是下游服务成功,上游服务失败会出现异常io.seata.core.exception.GlobalTransactionException:Could not found global transaction xid = 192.168.0.2:8091:2011766308, may be has finished.
需要一段时间后lock_tableglobal_table才会被清理干净,虽然事务会回滚,但是中途会造成很长时间的检查事务是否已被提交等等。
我自己有几种思路:

  1. 注意对用户的限流(这里所说的限流不是sentinel或hystrix的熔断降级那的限流,sentinel是针对服务本身的限流只用来防止服务超载挂掉而引发的服务雪崩,我们要做的是针对用户IP+URL的限流)

  2. 在下游服务先进行扣金额扣库存等操作,这样可以尽可能保证不会出问题。

  3. 加入csrf_token 用来防止重放攻击,毕竟csrf_token除了防御csrf攻击还可以用来干这事。

  4. 检查httpreferer是否来自正确的请求。

  5. 可以适当减少client.rm.lock.retryTimes 的重试次数,默认为30次
    client.rm.lock.retryInterval为重试间隔 默认10毫秒,看情况修改。从上面2个参数我们可以得出恶意请求在事务中一次最坏的情况是300ms,这还不算服务retry的时间。

一般这种分布式事务肯定不是用在对着一个商品不停的减库存这样的地方,这种秒杀肯定是redis+消息中间件,所以主要是为了防止某些恶意请求,比如黑客并发请求某服务,造成一直去判断全局事务之前的事务完成了没

手动解绑和绑定事务

RootContext.getXID() 可以直接获取到XID,我们可以在中途控制排除不需要在事务内的服务。

String xid = RootContext.getXID();
RootContext.unbind();//解绑
//中途做一些与事务无关的事。比如日志服务等等 排除掉,然后
RootContext.bind(xid);//再绑回来

手动控制事务流程

我们还可以自定义事务整个流程,下面只写了begin commit rollback,其中还有suspendresume等方法,用来暂停和恢复事务,suspend的参数是表示是否解绑xid

GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
// 超时时间 , 所在服务
tx.begin(30000, "user-service"); //30秒
//第二个参数transactionName 会在global_table中体现,可有可无,默认为default

try{
 //todo something
 //可以手动进行提交
 tx.commit();
}catch (Exception ignored){
 //如果捕获异常 可以手动进行回滚
 tx.rollback();
}

上面的例子就是我们自己来控制事务流程,如果有需要可以用AOP自己实现,一般情况下@GlobalTransaction已经够用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事干写博客玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值