分布式事务

    xiaoxiao2022-07-12  157

    一、分布式事务

    事务是程序执行的逻辑单元,一组操作要么全部成功,要么全部失败

    分布式环境下,对系统进行划分,比如电商项目,会将系统拆分成不同的服务,比如订单服务,积分服务,库存服务,寻源服务等等。

    订单生成流程:

    修改支付状态为已支付调用积分服务扣减使用的积分调用库存服务扣减库存调用仓储系统生成物流信息

    订单生成流程中如果任一步骤失败,由于在该服务之前其它服务已经完成,就会造成数据不一致。明明没有扣减库存,却使用了积分,并且支付亦显示完成。

    二、两阶段提交

    两阶段: 准备阶段和提交阶段

    角色: 事务的发起者称协调者,事务的执行者称参与者

    思路:

    Prepare阶段:

    协调者首先向所有参与者发送事务请求每个参与者执行相关事务执行成功不提交事务,向协调者返回信息执行失败,也向协调者返回信息

    Commit阶段:

    协调者收到success请求,向所有参与者发送提交请求,并释放事务期间占用的资源,各参与者提交结束返回ack信息,当协调者收到所有参与者的ack,完成本次事务提交协调者收到FAIL请求,向所有参与者发送回滚请求,参与者通过数据的undo Log进行回滚,并释放事务期间占用的资源,各个参与者向协调者反馈ack信息,当协调者收到所有参与者的ack,完成本次事务提交

    两阶段提交实现起来非常简单,但是:

    在分布式网络通信过程中,很容易造成消息丢失,延迟

    2PC方案缺点:

    性能问题。执行过程中,各个参与者处于阻塞状态,事务运行期间大量占用数据库资源,占用时间也比较长协调者单点故障问题。协调者是2PC的核心,一旦协调者挂掉,会导致参与者收不到提交或者回滚的通知,从而导致参与者处于事务无法完成状态数据一致性问题。第二阶段如果发生局部网络问题,一部分参与者收到提交信息,一部分没收到,导致数据不一致

    三、三阶段提交

    在2PC基础上,增加一个检查所有参与者健康状态阶段。

    canCommit:

    协调者向所有参与者发出包含事务内容的 canCommit 请求,询问是否可以提交事务,并等待所有参与者答复。参与者收到 canCommit 请求后,如果认为可以执行事务操作,则反馈 yes 并进入预备状态,否则反馈 no。

    preCommit:

    阶段 1 所有参与者均反馈 yes,参与者预执行事务

    协调者向所有参与者发出 preCommit 请求,进入准备阶段

    参与者接收preCommit请求,开始执行事务,但不提交事务

    参与者向协调者反馈信息,成功或者失败

    阶段 1 任何一个参与者反馈 no 或者没有收到任何反馈(超时或者消息丢失),中断事务

    协调者向所有参与者发出 abort 请求。无论是否收到协调者发出的 abort 请求,只要在等待协调者请求过程中出现超时,参与者均会中断事务

    do Commit:

    阶段2所有参与者反馈成功信息

    协调者向所有参与者发送提交请求参与者收到commit请求后会提交事务,释放数据库资源所有参与者反馈ack信息协调者接收所有参与者信息后完成事务提交

    阶段2任一参与者反馈No信息

    协调者向所有参与者发送回滚请求参与者进行回滚操作,释放事务占据的资源所有参与者均向协调者反馈信息协调者接收所有参与者信息后完成事务中断

    四、TCC事务

    补偿事务: 针对每个操作都需要注册一个与其对应的回滚(补偿)操作

    Try阶段:主要是对业务系统做检测及资源预锁

    Confirm阶段:确认执行业务操作

    Cancel阶段:取消执行业务操作

    TCC事务是基于二阶段的编程模型,不过2PC通常都是在跨库的DB层面,而TCC本质上就是一个应用层面的2PC,需要通过业务逻辑来实现,代码侵入性很强

    在订单生成流程中,使用TCC事务:

    try阶段:

    将订单状态改为支付中调用积分服务占用积分调用库存服务预锁库存调用仓储信息生成预发货单

    Try阶段如果全部调用成功,进入Confirm阶段进行正式调用,如果有一个服务调用失败,前面其它服务进行回滚。

    注:在 TCC 事务机制中认为,如果在 Try 阶段能正常的预留资源,那 Confirm 一定能完整正确的提交。所以Confirm 和 Cancel 操作必须满足幂等性,如果失败的会进行不断重试直到成功为止

    使用TCC分布式框架感知三个阶段状态,我们只需要编写三个状态的逻辑代码。如果提供服务节点发生宕机,TCC事务框架会记录一些分布式事务的活动日志的,可以在磁盘上的日志文件里记录,也可以在数据库里记录,保存下来分布式事务运行的各个阶段和状态,节点重启后会重新进行原来的操作

    最新回复(0)