分布式事务-2PC、3PC、TCC全方面对比

一、定义&优缺点

1. 2PC(两阶段提交)
  • 原理:将事务提交过程分为准备阶段和提交阶段。协调者先询问所有参与者是否可以提交(准备阶段),若所有参与者都同意,则执行提交操作(提交阶段);若有任何一个参与者不同意,则执行回滚操作。
  • 优点:实现相对简单,能够保证强一致性,在数据库事务等场景中应用广泛。
  • 缺点:存在阻塞问题,即参与者在等待协调者的指令时可能会一直处于等待状态;协调者单点故障会导致整个系统不可用,影响系统的可靠性和可用性。
2. 3PC(三阶段提交)
  • 原理:在2PC的基础上增加了一个预提交阶段。协调者先发送预提交请求,参与者收到后进入预提交状态;若所有参与者都准备好,则协调者再发送提交请求,参与者执行提交操作;若协调者未收到所有参与者的响应,则发送回滚请求。
  • 优点:减少了阻塞问题,因为参与者在预提交阶段有一定的时间限制,不会一直等待协调者的指令;在一定程度上提高了系统的可用性。
  • 缺点:仍然存在数据不一致的风险,例如在协调者发送提交请求后,部分参与者可能因网络问题未收到请求而未提交;实现复杂度较高,需要处理更多的状态和消息。
3. TCC(Try - Confirm - Cancel)
  • 原理:将一个业务操作分为Try、Confirm和Cancel三个阶段。Try阶段主要是预留业务资源,检查业务规则是否满足;Confirm阶段是在Try阶段成功的基础上,确认执行业务操作;Cancel阶段是在Try阶段失败或需要回滚时,取消预留的资源。
  • 优点:适用于业务逻辑复杂的场景,具有较高的灵活性,可以根据业务需求自定义Try、Confirm和Cancel的具体操作;能够实现最终一致性,在分布式系统中应用广泛。
  • 缺点:需要业务代码实现Try、Confirm和Cancel逻辑,实现复杂度较高;对业务系统的侵入性较大,需要修改原有的业务代码。

二、流程图对比

1. 2PC流程图
开始
协调者发送准备请求
所有参与者都同意?
协调者发送提交请求
协调者发送回滚请求
所有参与者都提交成功?
结束
协调者发送回滚请求
所有参与者都回滚成功?
2. 3PC流程图
开始
协调者发送预提交请求
所有参与者都同意?
协调者发送提交请求
协调者发送回滚请求
所有参与者都提交成功?
结束
协调者发送回滚请求
所有参与者都回滚成功?
3. TCC流程图
开始
客户端发起Try请求
业务系统执行Try操作
Try操作成功?
客户端发起Confirm请求
客户端发起Cancel请求
业务系统执行Confirm操作
业务系统执行Cancel操作
结束

三、表格对比

特性2PC3PCTCC
阶段数233
阻塞问题存在减少不存在
数据一致性强一致弱一致最终一致
实现复杂度
适用场景数据库事务对阻塞敏感的场景业务逻辑复杂的场景
对业务侵入性
可靠性受协调者单点故障影响有一定提高但仍存在数据不一致风险较高,通过最终一致性保证

四、Java代码对比

1. 2PC示例代码
import java.util.List;

// 参与者接口
interface Participant {
    boolean prepare();
    void commit();
    void rollback();
}

// 协调者类
class TwoPhaseCommitCoordinator {
    public void execute(List<Participant> participants) {
        // 准备阶段
        boolean allPrepared = participants.stream().allMatch(Participant::prepare);
        if (allPrepared) {
            // 提交阶段
            participants.forEach(Participant::commit);
        } else {
            // 回滚阶段
            participants.forEach(Participant::rollback);
        }
    }
}

// 示例参与者类
class ExampleParticipant implements Participant {
    @Override
    public boolean prepare() {
        // 模拟准备操作
        System.out.println("Participant is preparing...");
        return true; // 假设准备成功
    }

    @Override
    public void commit() {
        // 模拟提交操作
        System.out.println("Participant is committing...");
    }

    @Override
    public void rollback() {
        // 模拟回滚操作
        System.out.println("Participant is rolling back...");
    }
}

// 测试类
public class TwoPhaseCommitTest {
    public static void main(String[] args) {
        Participant participant1 = new ExampleParticipant();
        Participant participant2 = new ExampleParticipant();
        List<Participant> participants = List.of(participant1, participant2);

        TwoPhaseCommitCoordinator coordinator = new TwoPhaseCommitCoordinator();
        coordinator.execute(participants);
    }
}
2. 3PC示例代码
import java.util.List;

// 参与者接口
interface Participant {
    boolean prePrepare();
    boolean prepare();
    void commit();
    void rollback();
}

// 协调者类
class ThreePhaseCommitCoordinator {
    public void execute(List<Participant> participants) {
        // 预准备阶段
        boolean allPrePrepared = participants.stream().allMatch(Participant::prePrepare);
        if (allPrePrepared) {
            // 准备阶段
            boolean allPrepared = participants.stream().allMatch(Participant::prepare);
            if (allPrepared) {
                // 提交阶段
                participants.forEach(Participant::commit);
            } else {
                // 回滚阶段
                participants.forEach(Participant::rollback);
            }
        } else {
            // 回滚阶段
            participants.forEach(Participant::rollback);
        }
    }
}

// 示例参与者类
class ExampleParticipant3PC implements Participant {
    @Override
    public boolean prePrepare() {
        // 模拟预准备操作
        System.out.println("Participant is pre - preparing...");
        return true; // 假设预准备成功
    }

    @Override
    public boolean prepare() {
        // 模拟准备操作
        System.out.println("Participant is preparing...");
        return true; // 假设准备成功
    }

    @Override
    public void commit() {
        // 模拟提交操作
        System.out.println("Participant is committing...");
    }

    @Override
    public void rollback() {
        // 模拟回滚操作
        System.out.println("Participant is rolling back...");
    }
}

// 测试类
public class ThreePhaseCommitTest {
    public static void main(String[] args) {
        Participant participant1 = new ExampleParticipant3PC();
        Participant participant2 = new ExampleParticipant3PC();
        List<Participant> participants = List.of(participant1, participant2);

        ThreePhaseCommitCoordinator coordinator = new ThreePhaseCommitCoordinator();
        coordinator.execute(participants);
    }
}
3. TCC示例代码
import java.util.List;

// 参与者接口
interface Participant {
    boolean tryOperation();
    void confirm();
    void cancel();
}

// 协调者类
class TccCoordinator {
    public void execute(List<Participant> participants) {
        // Try阶段
        boolean allTried = participants.stream().allMatch(Participant::tryOperation);
        if (allTried) {
            // Confirm阶段
            participants.forEach(Participant::confirm);
        } else {
            // Cancel阶段
            participants.forEach(Participant::cancel);
        }
    }
}

// 示例参与者类
class ExampleParticipantTCC implements Participant {
    @Override
    public boolean tryOperation() {
        // 模拟Try操作
        System.out.println("Participant is trying...");
        return true; // 假设Try操作成功
    }

    @Override
    public void confirm() {
        // 模拟Confirm操作
        System.out.println("Participant is confirming...");
    }

    @Override
    public void cancel() {
        // 模拟Cancel操作
        System.out.println("Participant is canceling...");
    }
}

// 测试类
public class TccTest {
    public static void main(String[] args) {
        Participant participant1 = new ExampleParticipantTCC();
        Participant participant2 = new ExampleParticipantTCC();
        List<Participant> participants = List.of(participant1, participant2);

        TccCoordinator coordinator = new TccCoordinator();
        coordinator.execute(participants);
    }
}

五、关键维度总结

对比项2PC3PCTCC
性能低(全局锁阻塞)中(缩短锁时间)高(仅Try阶段锁)
一致性风险协调者故障导致数据不一致网络分区可能不一致最终一致,需补偿
业务侵入性低(依赖数据库)高(需实现Try/Confirm/Cancel)
适用场景传统金融跨库交易分布式系统减少阻塞高并发电商/支付

六、选型建议

  • 强一致性要求高:选2PC(如银行转账)
  • 可用性优先:选3PC或TCC(如秒杀系统)
  • 复杂业务补偿:TCC+消息队列组合(如订单创建+库存扣减)

3PC 替代方案‌:可用 Seata AT 模式(改进版 2PC,通过 undo_log 实现无阻塞提交)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值