首页 > 编程知识 正文

分布式事务消息队列解决方案,分布式基础及实际应用场景

时间:2023-05-05 14:15:08 阅读:48956 作者:2748

本文导航TCC异常场景幂等处理发生原因对策空回滚发生原因对策资源悬架发生原因对策3种异常总结幂等空回滚资源悬架通用项

TCC的异常场景

在分布式系统中,需要随时随地面临网络超时、网络重发、服务器宕机等问题。 因此,分布式事务框架即使作为安装在分布式系统中的框架型APP应用,也不可避免地存在这些问题。 具体来说,有以下常见问题。

处理空回滚资源(如应)以应对这些异常,需要TCC框架的支持和解决方案。

幂等处理的产生原因是网络抖动等原因,分布式事务框架必须能够保证重复调用同一个分布式事务中的一个分支事务的二阶段接口分支事务的两级接口Confirm/Cancel的幂等性如果两级接口不能保证幂等性,就会出现严重的问题,导致资源的再利用或再释放,进而导致业务障碍。

从上图中的红色部分可以看到,TC调用参与者的两级方法时发生异常(TC本身异常或网络异常丢失的结果)。 此时TC无法感知呼叫结果。 为了确保分布式事务到达终点,TC根据一定的规则重复调用参与者的两级方法。

为了应对幂等类型的问题,通常的手段是引入幂等字段来防止重放攻击。 对于分布式事务框架中的幂等问题,也可以祭出这一利器。 可以通过添加事务状态控制表来实现。 此表中的重要字段如下:

主事务ID分支事务ID分支事务状态其中1和2构成表的合并主键,用于唯一标识分布式事务中的分支事务。 3用于标识此分支事务的状态,共有三种状态。

INIT(I ) -已确认初始化-提交回滚-插入记录(如回滚幂)的时机是参与者的Try方法,此时分支事务状态初始化为init。 然后,在运行两个阶段的确认/取消时,其状态将设置为确认/回滚。

当TC反复调用两级接口时,参与者首先检索事务状态管理表中的相应记录以检查事务状态。 如果状态已经确认/回滚,则参与者已经完成相应的处理,不需要再次执行,可以将幂等成功结果直接返回给TC,以帮助推动分布式事务。 添加乘方等记录的写入和读取判断后,时序图如下所示(

回滚发生原因的定义,如上所述,在没有调用参与者的Try方法的情况下,需要调用两级Cancel方法,Cancel方法识别那时是否执行了Try的方法。 如果尚未运行Try,则表示此取消操作无效。 也就是说,这次取消是空回滚。 如果Try已经运行,则执行常规回滚逻辑。

如上图所示,红色部分的一个阶段的Try可能会失败。

首先,启动器在调用参与者之前,会向TC申请启动分布式事务。 然后,启动器通常调用参与者的一个阶段的方法,在呼叫实际发生之前,断开拦截器感知这次的Try呼叫,并写入分支事务记录。 之后,在实际调用参与者的Try方法时发生了异常。 异常的原因可能是启动器停机、网络抖动等。

总之,虽然Try方法未成功执行,但此时分布式事务和分支事务已经落入库中。 在以下两种情况下触发分布式事务回滚:

如果启动器确定当前分布式事务不成功,主动通知TC分布式事务超时,被动启动回滚并启动回滚操作,则TC将对与该分布式事务关联的分支事务执行其二级cannent 在取消期间,Try尚未成功,并触发了空回滚。 如果不防止回滚,可能会导致资源的无效释放。 也就是说,在不保留资源的情况下释放资源,造成故障。

可以发现,为了解决空回滚问题,解决方案必须使得参与者能够识别在两级Cancel方法中是否执行了一级Try。

显然,可以继续利用事务状态控制表来实现这一功能。

为了确保幂等性,我们说在Try方法成功执行后,将插入一条指示分支事务处于INIT状态的记录。 因此,在调用后续的两个阶段的Cancel方法时,可以通过查询控制表中的相应记录来进行判断。 如果记录存在,且状态为INIT,则表示阶段已成功运行,可以成功执行回滚操作并释放保留的资源。 如果记录不存在,则表示阶段未运行,这次是空回滚,不会释放资源。

时间图如下。

资源悬挂产生的原因悬挂,顾名思义,就是有被悬挂之后就无法处理的资源。 那么,在什么情况下会发生这种现象呢?

上一节中提到null回滚意味着一个阶段Try未成功执行,两个阶段Cancel调用TC来回滚整个分布式事务。

但是,在极端情况下,参与者的阶段Try在分布式事务结束之前不会运行,参与者根据业务需要保留相关资源。 保留资源仅可用于当前事务,但分布式事务此时已结束,此后没有处理这些保留资源的手段。 这样,资源就可以吊起来了。

虽然这样的一个阶段晚于两个阶段执行看起来是不可能的,但是仔细想想RPC调用的时机,实际上这种情况在复杂多变的网络中已经足够可行。 下一个时机说明了这种可能性:

启动器通过RPC调用参与者的阶段Try,但发生网络拥塞导致RPC超时的RPC

超时后,TC会回滚分布式事务(可能是发起方主动通知TC回滚或者是TC发现事务超时后回滚),调用已注册的各个参与方的二阶段Cancel参与方空回滚后,发起方对参与者的一阶段Try才开始执行,进行资源预留从而形成悬挂

使用时序图来描述,红色部分为产生资源悬挂的关键步骤:

应对策略

资源悬挂的本质原因在于,一阶段和二阶段的执行顺序没有被严格地保证。所以相应的解决方案还是通过读取事务状态控制表的事务状态。

前面在幂等方案的讨论中说过:

幂等记录的插入时机是参与者的Try方法,此时的分支事务状态会被初始化为INIT。然后当二阶段的Confirm/Cancel执行时会将其状态置为CONFIRMED/ROLLBACKED。

由于悬挂的产生背景是一阶段方法根本就未执行,所以此时事务控制记录是不存在的,需要在二阶段中处理ROLLBACK的情况(因为超时后触发回滚不可能存在二阶段为CONFIRM)。

处理方案为在判断为空回滚的场景下(体现在对应一阶段事务控制记录不存在),插入一条状态为ROLLBACKED的控制记录。

那么下次当一阶段Try抵达执行的时候,首先会尝试插入状态为INIT的事务控制记录。如果插入失败,表示当前分支事务的记录已经存在,Try无需继续执行。有几种可能性会导致此情形:

一阶段Try重复请求,网络抖动情况可能发生,可以理解为命中幂等二阶段插入了防悬挂记录,一阶段不可继续执行

时序图描述如下,蓝色部分为防止资源悬挂增加的检查项:

三种异常总结

前面讨论了分布式事务三种典型的异常类型,它们的解决方案都依赖于一张事务状态控制表。我们来尝试总结一下它们各自的特点。

幂等

问题:TC重复调用二阶段
解决:事务状态控制记录作为控制手段,只有存在INIT记录时才执行,存在CONFIRMED/ROLLBACKED记录时不再执行

空回滚

问题:TC回滚事务调用二阶段,但一阶段尚未执行
解决:事务状态控制记录作为控制手段,无记录时即为空回滚

资源悬挂

问题:TC回滚事务调用二阶段完成空回滚后,一阶段执行成功
解决:事务状态控制记录作为控制手段,二阶段发现无记录时插入记录,一阶段执行时检查记录是否存在

共通点 核心的解决方案就是事务状态控制表幂等控制作为最基础的异常处理手段;资源悬挂的前置条件是空回滚,所以发生空回滚时会插入一条状态为ROLLBACKED的控制记录

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。